zoukankan      html  css  js  c++  java
  • 22天学习java基础笔记之day15-20

    Day15-20集合框架

    一、集合的由来

            如果我们要操作很多对象,我们就要把很多对象进行存储。这个时候,我们会想到了我们前面学过数组,那么我们可以把自定义对象放到数组中。

    为什么我们不采用数组存对象呢?因为数组长度是固定,而我们很多时候对对象的个数是不确定的。所以,我们产生了集合框架,它是用于存储对象的。

    1、集合和数组的区别

            A:集合长度是可变的,集合中不能存储基本数据类型值,只能存储对象。

            B:数组的长度是固定的,可以存储对象,也可以存储基本数据类型。

    什么时候用哪个?

            长度不固定,用集合。

            长度固定,可以集合,可用数组。

    2、集合的体系结构

    由于每种容器的数据结构不同,所以我们集合框架中有很多种容器。这个时候,我们把容器进行不断的向上抽取,最终形成了集合的体系结构。

            Collection

                    |--List

                            |--ArrayList

                            |--Vector

                            |--LinkedList

                    |--Set

                            |--HashSet

                            |--TreeSet

            按照我们学习体系的习惯:先学习顶层对象,后使用底层对象。

    二、collection接口   

    1、添加

    Boolean add(E e):在集合中添加一个对象,如果添加成功,返回true,如果失败,返回false

    Boolean addAll(Collection<?extend E> e):在集合中添加另一个集合,成功true,失败false;

    2、删除

    Boolean remove(object obj):删除一个对象,会改变集合的长度

    Boolean removeAll(Colleciton con);删除一个集合,还有两个集合中相同的元素

    void clear():删除所有

    3、判断

    Boolean contains(object obj):在集合中是否包含指定的对象

    Boolean containsAll(Collection con):在集合是否包含另一个集合

    Boolean isEmpty( ):判断集合是否为空

    4、获取

    int size( )得到集合的尺寸大小      数组:length   字符串:length( );

    Iterator iterator( )取出元素的方式。迭代器。该对象必须依赖于绝缘体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在容器中进行内部实现的,对于使用容器者而言,绝缘体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,也就是iterator方法,Iterator接口就是对所有的collection容器进行元素取出的公共接口。

    将每一个容器中的取出方式进行了封装,并对外暴露,这样无论是什么容器或者数据结构,只要内部取出方式实现了Iterator接口,都可以通过该接口取出这些容器中的元素。

    他的出现,将容器的取出方式和容器的数据结构相分离,降低了耦合性,而取出方式因为直接在访问容器的元素,并依赖具体的数据结构,所以被定义在了容器中。通过内部类来实现Iterator接口。

    Collection c = new ArrayList();

                    c.add("hello");

                    Iteratot it = c.iterator();//返回的是Iteratot的子类对象

                    while(it.hasNext()){

                            String str = (String)it.next();

                            System.out.println(str);

                    }

    for(object obj:con)用于数组和集合(高级for循环)

    注意:迭代要强转,只能有一个next( )方法,否则会有NoSuchElementException异常。

    5、交集

    boolean retainAll(Collection c):返回两个集合的交集元素,删除其他元素,功能和removeAll相反。有A,B两个集合,做完交集后,A集合中的元素发生变化,取得是A和B相同的元素,B不变化。boolean值的问题-------->只要A集合变化,那么返回true.否则false

                     

    6、集合转数组

    Object[] toArray():把集合转换成对象。

    三、List接口

    有序(存入和取出的顺序一致,)元素都有索引(角标),元素可以重复。

    特有的常见方法:有一个共性特点就是都可以操作角标,可以完成对元素的增删改查

    规律:凡是有索引的容器,都有增删改查的方法。

    1、添加

    void add(index,element):在指定位置增加元素

    void add(index,collection):在指定位置添加集合

    2、删除

    Object remove(index):删除指定的元素----获取并删除

    3、修改

    Object set(index,element):在指定位置改变元素,并返回被替换掉的元素。

    4、获取

    Object get(index):获取指定的元素

    int subList(startindex,iendndex):获取子列表

    int indexOf(object ):返回对象所在的位置

    int lastIndexOf(object):返回对象最后出现的位置

    ListIterator:拥有了对元素进行增删改查的方法------->list特有的!

    5List接口的子类

    Vector:内部是数组数据结构,是线程安全的。增删查询都很慢

    ArrayList:内部是数组数据结构,是不同步的,代替了vector.,查询的速度快

            内存原理:

            在arrayList集合中,是一种线性表,每个对象存储都是有序的,用角标确定对象所存储的位置,查询时,直接通过角标进行查询,速度会很快,但是如果要进行增添、修改、删除操作的话,就要影响后面角标的对象,大部分对象都要移动,直接影响运行效率。

    ListkedList:内部是链表数据结构,是不同步的,增删元素的速度很快

            内存原理:

            LinkedList是一种链式存储方式,在每个对象中都存储有下一个对象的地址。所以要查询集合中的对象,必须通过地址值来逐个访问,首先从表头开始,逐一向下一个进行询问,直到找到为止,所以这样导致查询对象相对于arrayList来说非常慢,但是他有一个优点,增加、删除、修改就很快,如果要增加一个对象,直接把这个对象的地址赋给上一个对象,并存储下一个对象的地址。所以修改和删除也是对地址进行操作。大大提高运行效率。

    四、Set接口

    1、特点

    元素不能重复,无序,Set接口中的方法和collection的方法一样

    HashSet:内部实际结构是哈希表,是不同步的。

    哈希表:将对象经过哈希算法计算成该对象的哈希值,并把哈希值存放在哈希表中,其实哈希值就相当于数组中的角标。所以在查找的时候直接根据哈希值查询,速度很快。

    哈希表确定元素是否相同

    1. 判断的是两个元素的哈希值是否相同,如果相同,再判断两个对象的内容是否相同
    2. 判断哈希值相同,其实判断的是对象的hashcode的方法,判断内容相同,用的是equlas方法

    注意:如果哈希值不同,是不用判断equals.

    Hahset集合数据是哈希表,所以存储元素的时候,使用的元素的hashcode方法来确定位置,如果位置相同,在通过元素的equals来确定是否相同。也就是通过对象的hashcode和equals方法来完成对象唯一性的,如果对象的hashcode值不同,那么不用判断equals方法,就直接存储到哈希表中,如果对象的hashcode值相同,那么要再次判断对象的equals 方法是否为true,如果为true,视为相同元素,不存,如果为false,那么视为不同元素,就进行存储。

    记住:如果元素要存储到hashset集合中,必须覆盖hashcode方法和equals方法,一般情况下,如果定义的类会产生很多对象,比如人,学生,数,通常都需要覆盖equlas,hashcode方法。建立对象判断是否相同的依据。

     

    TreeSet可以对集合中的元素进行排序,是不不同步的,

    判断元素唯一性的方式:即使根据比较方法的返回结果是否是0,是0,就是相同的元素,不存,

    1. Treeset对元素进行排序的方式一:

    让元素自身具备比较功能,就需要实现comparable接口,覆盖comparaTo( )方法。如果不要按照对象中具备的自然顺序进行排序,如果对象中不具备自然顺序,怎么办?

    1. 可以使用treeset集合第二种排序方式二:

    让集合自身比较功能,定义一个类实现comparator接口,覆盖compare方法。将该类对象作为参数传递给treeset集合的构造函数。

    2、集合的使用技巧

    同步与非同步:

    明确具体集合对象名称的后缀,如果后缀是List都所属于List体系,通常是非同步的,如果后缀是Set都所属set体系,通常是非同步的;这些体系的其他子类对象,后缀不是所属接口名的,一般都是同步的。如vector

    数据结构:

    前缀是数据结构,后缀是所属体系。

    ArrayList:看到Array,明确是数组结构,查询快。

    需要唯一吗?

    需要:set

      需要制定顺序吗:

                 需要:TreeSet

               不需要:hashset

               但是想要一个和存储一致的顺序(有序):linkedhashset

    不需要:list

         选要频繁增删吗:

                 需要:linkedlist

               不需要:arraylist

    如果记录每一个容器的结构和所属体系呢?

    看名字!

    List

       Arraylist

       Linkedlist

    Set

       Hashset

       Treeset

    后缀名就是该集合所属的体系。

    前缀名就是该集合的数据结构。

    看到array:就要想到数组,就要想到查询快,有角标。

    看到link:就要想到链表,就要想到增删快,就要想到 add get remove+first last的方法。

    看到hash:就要想到哈希表,就要想到唯一性,就要想到hashcode和equals

    看到tree:就要想到排序,想到二叉树,就要想到comparable和comparator

    通常这些常用的是线程不安全的。

    五、泛型

    Jdk1.5出现的安全机制。解决类型安全问题,只能用于编译时期,提高安全性

    1、好处

    • 将运行时期的问题classCastExceptoin转到了编译时期。
    • 避免了强制转换的麻烦。

    2、什么时候用

    当操作的引用数据类型不确定的时候,就使用泛型,将要操作的引用数据类型传入即可,其实<>就是一个用于接收具体引用数据类型的参数范围。

    在程序中,只要用到了带有<>的类或者接口,就要明确传入的引用数据类型。

    泛型技术是给编译器使用的技术,用于编译时期,确保了类型的安全。运行时,会将泛型去掉。生成的class问题中是不带泛型的,这个叫泛型的擦除。为什么擦除呢?因为为了兼容运行的类加载器。

    泛型的补偿:下运行时,通过获取元素的类型进行转换动作,不用使用者在强制转换了。

    泛型类:什么时候用?当类中的操作的引用数据类型不确定时候,就可以使用泛型类来表示。

    当方法静态时,不能访问类上定义的泛型,如果静态方法使用泛型,只能将泛型定义在方法上。写在返回值的前面。

    泛型接口:将泛型定义在接口上。

    泛型的通配符:?未知类型

     

    泛型的限定:?extends E--------->接收E类型或者E的子类型。

    ?extends E:接收E类型或者E的子类对象,上限

    一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患。

    ?super E:接收E类型或者E的父类对象,下限

    什么时候用下限呢?通常对集合中的元素进行取出操作时。可以用下限。 

     

    六、Map

    一次添加一对元素,conllection一次添加一个元素

    Conllection是单列集合,map是双列集合。其实map集合中存储的就是键值对。

    Map集合中必须保证键的唯一性。

    1、常用的方法

    1. 添加

        value put(key,value):费前一个和Key关联的值,如果没有返回null

    1. 删除

        void clear():清空Map集合。

        value remove(key):根据指定的Key翻出这个键值对。

    1. 判断

        Booelean containsKey(key):判断是否包含指定的建

            Boolean containsValue(value):判断是否包含指定的值

            Boolean isEmpty():判断是否为空

    1. 获取

    value get(key):通过键获取值,如果没有改建返回null,当然可以通过返回Null,来判断是否包含指定键。

    int size():获取键值对的大小

    2、从map中获取值的方法

    @Test

        public void show(){

            Map<Student,String> map = new HashMap<Student,String>();

            map.put(new Student("mm",23),"湖北");

            map.put(new Student("lisi",27),"北京");

            map.put(new Student("wangwu",29),"山东");

            map.put(new Student("zhaoliu",43),"四川");

            map.put(new Student("houqi",33),"深圳");

            map.put(new Student("maba",53),"江苏");

            map.put(new Student("wangcai",13),"浙江");

            /*for (Integer i : map.keySet()) {

                System.out.println(map.get(i));

            }*/

            for (Entry<Student,String> it : map.entrySet()) {

                Student s = it.getKey();

                String str = map.get(it.getKey());

              //System.out.println(it.getKey()+" "+map.get(it.getKey()));

                System.out.println(s.getName()+": "+s.getAge()+" "+str);

            }

        }

    Map常用的子类;

    Hashtable:内部结构是哈希表,是同步的,不允许Null作为建,null作为值,

    Properties:用来存储简直对型对配置文件的信息,可以和IO技术相结合。

    Hashmap:内部构造是哈希表,不是同步的。允许null键,null为null

    Treemap:内部构造是二叉树,不是同步的,可以对map集合进行排序

    给非同步的集合加锁

    非同步的----List list=new ArrayList();

    返回同步----list=Mycollecitions.sycList(list);

    Class Mycollections{

    Public List static sycList(List list){

                Return new MyList(list);

    }

    }

    Class MyList implements List{

       Private List list;

       Private static vfinal Object lock=new Object();

    MyList(List list){

                This.list=list;

    }

       Public Boolean add(Object obj){

      Synchoronized(lock){

                    Return list.add(obj);

           }

       }

       Public Boolean remove(Object obj){

    Synchoronized(lock){

                          Return list.remove(obj);

                 }

    }

    }

    3MapCollection的区别?

            1.collection是用于存储单列对象的集合,可以是一组单个对象,而map是存储双列对象集合,也就是以键值对的形式存储。是两组对象,一组是用来存储键,一组是存储值。

            2.collection增加的方法是add,mapput.

        3.如果要取出集合中的元素,collection可以直接使用迭代器,但是map不能直接用迭代器,可以先把Map集合转换成set集合,再用迭代器取出元素。

        4.如果没有映射关系,使用collection ,对象与对象之间产生映射关系就用map集合。

    4Map的练习(字母次数),明确查表的应用,注重思想?

    public class MapTest1 {

        /**

         * 1.将字符串转成字符数组

         * 2.因为字符串中单个字符和字符出现的个数产生了对应关系,所以使用了map集合

         * 3.对字符数组进行遍历,得到数组中的元素,并对其进行判断,非a到z,或A到Z不能进行操作

         * 4.定义一个计数器变量

         * 5.将数组中的元素取出来,得到元素和出现的次数,并存储在集合中

         * 6.将集合中的元素迭代,并以字符串的形式打印出来

         */

        public static void main(String[] args) {

            String str = "abwwbaabbwwdsdscabcssas";

            String s = getCount(str);

            System.out.println(s);

        }

        public static String getCount(String str){

            char[] chs = str.toCharArray();

    TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();

            for (char c : chs) {

                if(!(c>='a'&&c<='z'||c>='A'&&c<='Z')){

                    continue;

                }

                int count =1;

                Integer value = tm.get(c);

                if(value!=null){

                    count = ++value;

                }

                tm.put(c, count);

            }

            StringBuilder sb = new StringBuilder();

            for (char c : tm.keySet()) {

                sb.append(c).append("(").append(tm.get(c)).append(")");

            }

            return sb.toString();

        }

    }

    5Collecitons中常见方法举例?

        static <T extends Comparable<? super T>> void sort(List<T> list) :将集合进行排序,并可以指定集合参数的类型,要继承comparable接口,

        static void swap(List<?> list, int i, int j) :根据指定的位置交换集合中的元素

        static void shuffle(List<?> list) :对集合中元素位置随机发生变化

        static <T> int  binarySearch(List<? extends Comparable<? super T>> list, T key) :使用二分查找给出指定的值在集合中的位置

    static<T>List<T>synchronizedList(List<T> list)

    6CollectionCollections的区别?

    collection  

        collection是所有单列集合中的父接口,是以一组单个对象存储形式,根据需求,对象在内存中存储数据结构形式不同,collection就产生许多子接口,其中常用的是list接口和set接口,而ListArrayListlinkedList两个常用的实现类,它是有序可重复的,set接口有hashsettreeset两个实现类,是无序不可重复的。

    collections    

            他是对集合操作的一种工具类,类中的方法全部都是静态的,可以对集合的排序,交换位置,二分查找,元素顺序随机变化。等操作。      

    7Arrays常见方法?

    java.util.Arrays

    public class Arrays extends Object

     static <T> List<T> asList(T...a):将数组转换成List集合

             static int binarySearch(int[] a,int key):使用二叉树查找法早找指定元素在数组中的位置

             static int[] copyOf(int[] original,int newLength):指定数组的长度并复制到其他数组

             static int[] copyOfRange(int[] original, int from,int to):复制指定的范围

             static boolean equals(int[] a,int[] a1):判断两个数组是否相等,

             statid void fill(int[] a,int val):将数组中的值变为指定的值,相当于初始化值

             static int hashCode(int[] a):返回数组的哈希值

             static void sort(int[] a,int fromIndex,int toIndex):指定数组范围并进行排序

             static <T> String toString(int[]a):将数组转换成字符串

             static boolean deepEqasls(Object[] al,Object[] a2):判断两个对象的深度是否相等

    8、数组和集合转换,数组转集合为什么?集合转数组为什么?要注意什么?

            数组转集合:可以对数组中的元素通过集合中的方法进行操作,只要不影响其长度,可以使用集合中的任意方法。

        集合转数组:为了限制集合中元素操作,他只有一个length属性可以操作

        注意:不管是集合转数组还是数组转集合,长度是不可以改变的,不能对其进行增删操作。

    9、增强for循环和传统for循环的区别?foreach可以遍历map吗?什么时候使用map

    在循环多次的时候,传统的循环可以对其循环条件的控制,而增强for不能控制,增强for只能是简化书写,遍历集合或数组中的元素,

    不能直接遍历map集合,但是可以通过把map集合转成set集合后,再根据set集合迭代出元素。

    当分析问题时,发现存在着映射关系,这时可以考虑到数组和map

    10、可变参数的使用方式,和注意事项,并举例?

            可变参数的使用格式:

      1.int add(T... a):该函数可以添加多个同种类型的数据,相当于函数的参数是数组形式。

      2.int add(T a,T... a1):在传参数是,除了第一个为a,其他全部都是属于可变参数。

      注意:可变参数必须放在其他参数的最后边。

    传入的实参必须是根据形参的同种类型的参数

  • 相关阅读:
    SJTU T4143 推箱子
    Markdown基本语法
    命令行的操作——cd
    C++ ------- 类和对象
    数据结构------栈和队列
    MySQL------ 子查询
    MySQL------ SQL99语法
    C++------内存分区模型
    第三章------数据链路层
    MySQL------ SQL92语法
  • 原文地址:https://www.cnblogs.com/aohongzhu/p/12938749.html
Copyright © 2011-2022 走看看