浅析Java中的集合包(ArrayList,LinkedList,Vector, Stack,HashSet,TreeSet,HashMap,TreeMap)

    xiaoxiao2021-12-15  25

    集合包是Java中最常用的包,它最常用的有Collection和Map两个接口的实现类,Collection用于存放多个单对象,Map用于存放Key-Value形式的键值对。

            Collection中常用的又分为两种类型的接口:List和Set,两者最明显的差别为List支持放入重复的对象,而Set不支持。List接口常用的实现类有:ArrayList,LinkedList,Vector和Stack;Set接口常用的实现有HashSet,TreeSet。而Map的常用实现有TreeMap和HashMap。

    1. ArrayList基于数组方式实现,无容量的限制。

    2. ArrayList在执行插入元素时可能要扩容,在删除数组时并不会减少数组的容量(如希望相应的减少数组的容量,可以调用ArrayList的trimToSize()),在查找元素时需要遍历数组,对于非null的元素采取equals的方式寻找。

    3.ArrayList是非线程安全的。

    1. LinkedList基于双向链表机制实现。

    2. LinkedList在插入元素时,必须创建一个新的Entry对象,并切换相应元素的前后元素的引用;在查找元素时,须遍历列表;在删除元素时,要遍历列表,找到要删除的元素,然后从列表上将此元素删除即可。

    3. LinkedList是非线程安全的。

    从LinkedList和ArrayList的区别来看,我们可容易的得出什么时候使用ArrayList,什么时候使用LinkedList:

         1)对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。       2)  对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

    三、Vector

          和ArrayList的不同点有

          1) Vector是基于Synchronized实现的线程安全的ArrayList。即Vector是线程安全的。

          2)在插入元素时容量扩充的机制和ArrayList稍微有所不同,Vector是扩充2倍,并 可通过传入capacityIncrement来控制容量的扩充。 而ArrayList是扩充1.5倍并加1。

    四、Stack

          Stack继承与Vector,在Vector的基础上实现了Stack所要求的后进先出(LIFO)的弹出即压入操作,其提供了push,pop,peek等三个主要方法。

    五、HashSet

          1. HashSet基于HashMap实现,无容量限制。

          2. HashSet是非线程安全的。 

          3. HashSet不保证有序。

    六、TreeSet

          1、TreeSet基于TreeMap实现,支持排序。

          2、TreeSet是非线程安全的。

    从对HashSet和TreeSet的描述来看,TreeSet和HashSet一样,也是完全基于Map来实现的,并且都不支持get(int)来获取指定位置的元素(需要遍历获取),另外TreeSet还提供了一些排序方面的支持。例如传入Comparator实现、descendingSet以及descendingIterator等。 

    七、HashMap

           1、HashMap采用数组方式存储key,value构成的Entry对象,无容量限制。

           2、HashMap基于Key hash查找Entry对象存放到数组的位置,对于hash冲突采用链表的方式来解决。

           3、HashMap在插入元素时可能会要扩大数组的容量,在扩大容量时须要重新计算hash,并复制对象到新的数组中。

           4、HashMap是非线程安全的。

           5、HashMap遍历使用的是Iterator

    八、HashTable

          1、HashTable是线程安全的。

          2、HashTable中无论是Key,还是Value都不允许为null。

          3.   HashTable遍历使用的是Enumeration。

    曾经HashTable的应用非常广泛,HashMap是新框架中用来代替HashTable的类,也就是说建议使用HashMap,不要使用HashTable,可以使用ConcurrentHashMap。那么几者之间有什么区别呢?

          1、HashTable的内部存储结构

    HashTable和HashMap采用相同的存储机制,二者的实现基本一致,不同的是:

         1)、HashMap是非线程安全的,HashTable是线程安全的,内部的方法基本都是synchronized。

         2)、HashTable不允许有null值的存在。

    在HashTable中调用put方法时,如果key为null,直接抛出NullPointerException。其它细微的差别还有,比如初始化Entry数组的大小等等,但基本思想和HashMap一样。

           2、HashTable和 ConcurrentHashMap的比较

    ConcurrentHashMap是目前最好的线程安全的HashMap的实现。同样是线程安全的类,它与HashTable在同步方面有什么不同呢?

    HashTable使用synchronized关键字来确保同步,而Synchronized其实是对对象加锁,不论你是在方法前加synchronized还是语句块前加, 锁住的都是对象整体 , 但是ConcurrentHashMap的同步机制和这个不同,它不是加synchronized关键字,而是基于lock操作的,这样的目的是保证同步的时候,锁住的不是整个对象。事实上,ConcurrentHashMap可以满足concurrentLevel个线程并发无阻塞的操作集合对象。

    需要特别注意的是,我们在具体的项目开发中必须对HashMap的非线程安全保持足够的关注,如果在并发场景中不保持足够的同步,就有可能在执行HashMap.get是进入死循环,将CPU耗到100%。

           1、TreeMap是一个典型的基于红黑树的Map实现,因此它要求一定要有Key比较的方法,要么传入Comparator实现,要么key对象实现Comparable接口。

           2、TreeMap是非线程安全的。

    转载请注明原文地址: https://ju.6miu.com/read-1000244.html

    最新回复(0)