Java集合详细总结

Java集合总结

  • 什么是集合

           1.集合是一个容器,里面可以存放各种元素,就如同去超市购物时用到的购物袋。在集合中存储的都是对象的引用,并不是直接将对象存储再集合中。所有集合都在java.util包下。集合有几个类,不同的集合底层实现的是不同的数据结构。

  • 集合的继承结构图

           集合分两类,Collection 和 Map。其继承结构图分别如下图所示:

         1.Collection

在这里插入图片描述
           如上,Collection是一个接口,Collection接口实现了Iterable接口,表示Collection类集合都是可迭代的,可遍历的。Collection集合同时又有多个实现类,其中List和Set是较为常用的,以下初步说明两类集合:
          List: List是一个接口, List集合存储元素的的特点是有序可重复的,有序是因为存储的元素都有下标,从0开始,以1递增。同时List也有多个实现类,其中ArrayList,LinkedList,Vector相对比较常用:

          ArrayList: ArrayList实现了List接口,他有如下特点:
          1.ArrayList底层采用的是数组的数据结构,底层用的是Object[]数组,所以ArrayList对查询的效率很高,而对增删的效率较低,但是向末尾添加元素的时候效率也是很高的。
          2.ArrayList集合是非线程安全的。
          3.ArrayList集合的默认初始化容量是10(用无参构造创建集合的时候,刚创建的集合容量是0,添加第一个元素的时候容量会变成10),当添加的元素超过集合容量时(如容量10,添加第11个元素时),集合会进行自动扩容,每次扩容是原容量的1.5倍。
          4.底层扩容机制其实是数组的复制,将原来的数组复制到另一个内存更大的数组中,并将新元素添加到新的数组中。
          5.优化ArrayList:创建的时候给定一个预估的初始化容量,减少他的扩容次数。

          LinkedList: LinkedList实现了List接口,他有如下特点:
          1.LinkedList底层采用的是双向链表的数据结构,所以其增删的效率很高,但是查询的效率较低。
          2.链表中的元素再空间存储上,内存地址不连续。
          3.对于LinkedList来说,没有初始化容量,也没有扩容机制,直接再链表中添加即可。

          Vector: Vector实现了List接口,这种结合的底层也是采用的数组这种数据结构,但是与ArrayList集合不同的是,他是线程安全的,他的所有方法都有synchronized关键字修饰,但是效率较低,现在保证线程安全有别的方案,所以Vector使用较少了。


          Set: Collection的另一个比较重要的分支是Set,Set同样是一个接口,Set存储元素的特点是无序不可重复,Set集合中的元素没有下标。其实存在Set中的元素就是存在了Map集合的key中。Set同样也有多个实现类,HashSet和SortedSet比较常用:

          HashSet: 实际上HashSet集合在创建的时候,底层是创建了一个HashMap集合。向HashSet集合中存储元素,实际上是存储到了HaseMap的key中。所以HashSet和HashMap其实是类似的,底层也是哈希表的数据结构,默认初始化容量是16,扩容因子是0.75(当哈希表的数组的容量达到75%的时候开始扩容),扩容之后是原来的2倍。哈希表单向链表中的元素超过8个,单向链表会变成红黑树数据结构,而当红黑树的节点小于6个的时候又会重新变成单向链表。

           SortedSet: SortedSet是一个接口,该接口由于实现了Set接口,所以他的特点也是无需不可重复,但是放在Set集合中的元素可以自动排序,称为可排序集合。放到该集合中的元素是自动按大小排序的。在SortedSet下有一个实现类是TreeSet
           TreeSet: TreeSet集合底层实际上是TreeMap,创建TreeSet的时候实际上是创建了TreeMap,放在TreeSet中的元素实际是放在了TreeMap的key中。TreeMap底层采用的是二叉树的数据结构,所以可以自动排序。(取数据的时候采用的是中序遍历方式:左根右)



          2.Map
在这里插入图片描述

        Map集合和Collection集合在继承结构上没有任何关系;Map集合是以key-value的这种键值对的方式存储元素的;同样key和value都是存储对象的内存地址的;因为Map集合的key其实就是Set集合,所以所有Map集合key的特点:无序不可重复。Map下较为常用的集合有HashMap、HashTable、SortedMap:

        HashMap: HashMap实现了Map接口,底层使用的是哈希表的数据结构,是非线程安全的。默认初始化容量是16,扩容因子是0.75(当哈希表的数组的容量达到75%的时候开始扩容),扩容之后是原来的2倍。哈希表单向链表中的元素超过8个,单向链表会变成红黑树数据结构,而当红黑树的节点小于6个的时候又会重新变成单向链表,这种方式也是为了提高检索效率。HashMap集合的key和value是允许null的。

        HashTable: 同HashMap一样,HashTable集合底层也是哈希表的数据结构,但是不同的是HashTable是线程安全的,其中所有的方法都是由synchronized关键字修饰的,但是效率较低,现在基本不用了。HashTable集合的默认初始化容量是11,集合扩容是原容量的2倍+1(原容量*2+1)。HashTable的key和value不允许为空。
        Properties: Properties继承于HashTable,所以也是线程安全的。Properties在存储元素的时候key和value只支持String类型,不支持其他类型。Properties被称为属性类。

        SortedMap: SortedMap的特点和SortedSet一样,因为放在SortedSet中的元素实际就是放在了SortedMap的key中。其特点首先是无序不可重复,再之是可按照元素的大小自动排序,称为可排序集合。
        TreeMap: 继承于SortedMap,底层数据结构是二叉树,与TreeSet相同。



  • 集合的常用方法

       Collection中的公共方法(用ArrayList演示):
       1.add(E e):往集合中添加元素。

		ArrayList list = new ArrayList();
        list.add(1);//往集合中添加元素"1"

        2.size():返回int,表示此集合中的元素数。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list.size());//3

        3.clear() :清空集合。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.clear();//清空集合
        System.out.println(list.size());//0

        4.isEmpty() :判断集中是否为空。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list.isEmpty());//false
        list.clear();//清空集合
        System.out.println(list.isEmpty());//true

        5.toArray() :返回一个数组,将一个集合转换成一个数组。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        Object[] objects = list.toArray();
        for (Object o : objects){
            System.out.println(o);//1 2 3
        }

        6.contains(Object o) : 判断集合中是否包含某元素。该方法底层调用的是equals()方法比较的。如下:
        在Dog类没有重写equals()方法时,比较结果是false。
在这里插入图片描述
        Dog类重写equals()方法之后,返回值是true。
在这里插入图片描述
        remove(Object o): 从该集合中删除指定元素,同contains()方法,该方法底层也是调用的equals()方法。如下:
        在Dog类没有重写equals()方法时,最后结果是1,表示之前的元素并没有被删除。
在这里插入图片描述
        Dog类重写equals()方法之后,返回值是0,表示已经删除了集合中的元素。
在这里插入图片描述
总结:所以需要加入集合中的类最好重写equals()方法。

       List特有方法(用ArrayList演示):因为List集合中的元素是有下标的,所以他有自己的一系列特有方法,如下:
        1.add(int index, E element) :将指定的元素插入集合中的指定位置。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(1,3);
        for (Object o : list){
            System.out.println(o);//1 3 2
        }

        2.get(int index) :返回集合中指定位置的元素。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        System.out.println(list.get(1));//2

        3.indexOf(Object o) :对象第一次出现的索引。

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(2);
        System.out.println(list.indexOf(2));//1

        lastIndexOf(Object o) :对象最后一次出现的索引:

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(2);
        System.out.println(list.lastIndexOf(2));//2

以上两个方法同样是用equals()方法进行比较的。

        4.set(int index, E element) :修改指定位置元素。

 		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(2);
        list.set(2,3);
        for (Object o : list){
            System.out.println(o);//1 2 3
        }

        5.remove(int index) :删除指定位置的元素

		ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.remove(1);
        for (Object o : list){
            System.out.println(o);//1 3
        }







       ArrayList的构造方法: ArrayList(Collection<? extends E> c) : ArrayList的构造方法可以传入一个Collection集合,将这个Collection集合转换成一个ArrayList集合。

		Set set = new HashSet();
        set.add(1);
        set.add(3);
        set.add(4);
        ArrayList list = new ArrayList(set);






       Map的公共方法(用HashMap演示):
        1.clear() :清空集合。
        2.put(K key, V value) :向map中添加元素,以key-value的方式,如同Collection中的add方法。
        3.isEmpty():判断集合是否为空。
        4.size():返回集合的元素个数。
        5.get(Object key) :通过key获取value。

		Map map = new HashMap();
        map.put(1,"张三");
        map.put(2,"李四");
        System.out.println(map.get(2));//李四

        6.containsKey(Object key) :判断集合中是否包含某个key。
        containsValue(Object value) :判断集合中是否包含某个value。
        remove(Object key) :删除集合中对应的key的数据。
以上三个方法底层都是调用的equals()方法进行比较,所以最好放进集合中的类都重写equals()方法。
        7.keySet() :将Map中的key全部拿出来放进一个Set集合中,返回一个Set集合。其实Map的key就是一个Set集合。

		Map map = new HashMap();
        map.put(1,"张三");
        map.put(2,"李四");
        map.put(3,"李四");
        Set set = map.keySet();
        for (Object o : set){
            System.out.println(o);//1 2 3
        }

        8.values() :将Map集合中的values全部拿出来放进一个Collection中,返回一个Collection集合。

		Map map = new HashMap();
        map.put(1,"张三");
        map.put(2,"李四");
        map.put(3,"李四");
        Collection list = map.values();
        for (Object o : list){
            System.out.println(o);//张三  李四  李四
        }

        9.entrySet() :将Map转换为Set。该方法的返回值类型是Set<Map.Entry<K,V>>,这是一种类型名,是Map中的静态内部类。

		Map map = new HashMap();
        map.put(1,"张三");
        map.put(2,"李四");
        map.put(3,"李四");
        Set set = map.entrySet();
        for (Object o : set){
            System.out.println(o);//1=张三 2=李四 3=李四
        }







  • 集合的遍历

        Collection的遍历:
        第一种方法:因为Collection实现了Iterable接口,所以所有的集合都是可以使用迭代器遍历的,调用iterator()方法可以获得迭代器,在用循环就能完成遍历,如下:

		List list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        Iterator it = list.iterator();
        while (it.hasNext()){
            Object o = it.next();
            System.out.println(o);// 1 2 3
        }

Iterator有三个方法,next()、hasNext()、remove()。
hasNext()方法判断集合中是否含有下一个元素,
next()让迭代器返回下一个元素,
remove() 方法则是删除迭代器返回的最后一个元素,也就是删除迭代器当前所指定的元素。
但是值得注意的是,集合的结构发生改变,迭代器必须重新获取,否则会报异常
在这里插入图片描述
这里用list的remove()方法改变了集合的结构,所以会报异常。但是如果使用迭代器的remove()方法则不会改变集合的结构,迭代器类似一个快照。
在这里插入图片描述
结论:所以,一代改变集合的结构,则需要重新获取迭代器。
        第二种方法: 使用增强for循环遍历,代码简单,但是效率没有迭代器高。

		List list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        for (Object o :list){
            System.out.println(o);//1 2 3
        }





        Map集合的遍历:
        第一种方法: 获取所有的key,通过key获取value。
在这里插入图片描述
        第二种方法: 用entrySet()方法,直接将Map集合转为set集合,遍历set集合,每次取出一个node对象,在调用node.getkey(),node.getValue(),获取key和value。 这种效率比第一种方法高,适合数据量大的时候使用。
在这里插入图片描述



  • 关于SortedSet和SortedMap为什么能对存储的元素进行自动排序

在这里插入图片描述
从TreeMap的put方法的源代码上我们可以看到这里调用了compareTo()方法,这个compareTo()方法来自一个Comparable接口。

所以我们可以了解到,需要SortedMap集合对元素进行自动排序,必须将放入SortedMap中的元素类实现Comparable,并且实现这个接口中的compareTo()方法,在这个方法中编写比较规则,集合才能自动排序。

在这里插入图片描述
如上,要是Dog类没有实现Comparable接口,调用add()方法则直接报异常。
在这里插入图片描述
Dog类实现了Comparable接口,并重写了CompareTo()方法之后,就可以完成自动排序了。

以上方法是第一种可以让SortedMap和SortedSet实现自动排序的功能,还有第二种方法,使用比较器:
比较器需要实现java.util.Comparator接口,并重写compare()方法。在构建TreeMap集合的时候使用构造方法将比较器传入,就可以实现元素的自动排序功能,如下图:
在这里插入图片描述
最终结论: 放在TreeSet或者TreeMap中的元素,想要排序,有两种方式
1.实现Comparable接口。
2.创建比较器传入。





  • 关于HashMap底层的哈希表数据结构解释。

直接上老杜的图:
在这里插入图片描述
注:上图中的注意中说同一个链表上所有的hash值相同,其则不然,有可能是不同的,当时笔记没有改过来。

结论:放在HashMap集合key部分的以及放在HashSet集合中的元素,需要同时重写hashCode()方法和equals()方法。

  • 关于集合工具类Collections

java.util.Collections类中有几个方法:
1.Collections.synchronizedList(List list)方法,可以将非线程安全的集合变成线程安全的。

		List list = new ArrayList();
        List list2 = Collections.synchronizedList(list);

2.sort(List list)方法,对集合进行排序。跟TreeSet相同,需要集合中的元素实现comparable接口,或者使用sort(List list,Comparator c)方法传入比较器。
在这里插入图片描述
运用该方法,也可以对Set集合进行排序,首先用ArrayList的构造方法将Set集合转为ArrayList集合,在使用sort(List list)方法进行排序。





以上便是我对集合章节的总结。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值