本篇文章将尝试回答一些Java集合类常见的问题,以作知识梳理之用。
就实现方式而言:
ArrayList是以数组的方式实现的列表。
LinkList是以双向链表的形式实现的列表。
就使用场景而言:
ArrayList适合于随机查询要求比较多的场景,因为其内部实现是一个数组,所以可以快速定位元素的位置。它的缺点是不适合插入删除操作,其原因是因为Java的数组是静态的。这两种操作需要对数组进行调整,其中不可避免的是需要调整元素的位置,这一操作只能通过数组拷贝的形式来完成,效率较低,如果遇上要扩容的情况,效率会更加的低。因此,如果能够在实例化ArrayList的时候传入所需的容量大小,减少扩容的操作,可以提高不少效率。
LinkList适用于需要频繁插入删除操作的节点,因为其实现方式是通过链表的形式,不用进行类似于ArrayList数组拷贝以及元素位置的调整,只需要调整节点的前驱指针和后继指针即可。其缺点是不适合频繁的随机查询,因为链表的查询是通过从头节点开始遍历匹配,因此性能较差。
SynchronizedList的实现方式是通过同步代码块的形式实现同步,而Vector使用的是同步方法,效率上而言,Vector的效率要低一些。
此外,SynchronizedList的扩展性和灵活性很好,它可以将所有的List的子类转化为线程安全的类,同时可以指定锁的对象。不过,使用SynchronizedList的时候,进行遍历时要手动进行同步处理,因为SynchronizedList的iterator并没有进行同步。
这三个数据类型都实现了Map接口,本质上的功能差别不大,除了HashTable不可以接受null之外。
它们最大的区别是在线程安全方面,HashMap、HashTable的线程安全性就好像,ArrayList和Vector一样,HashTable是一个使用同步方式来维护线程安全的Map,效率比HashMap要低上许多。ConcurrentHashMap是另一个线程安全的Map,它的内部采用了分段锁的机制,使得它的效率比HashTable高上不少,同时还可以保证线程安全。
Set中不要求元素按顺序进行存储,且不允许存储相同的元素,而List则不可以。从Set的实现来看,其内部维护了一个Map来存储元素,元素是作为Map的Key存储的。Map会通过比较元素的hashcode以及equals来判断是否是同一个对象,因此Set可以保证元素不重复。
在JDK1.7版本的HashMap中,如果遇到hash值相同的元素之后,会使用链表来将元素链接起来。然而,在JDK1.8中,为了提升查询的效率,当hash值相同的元素达到一定数量的时候,会采用红黑树的方式来存储元素。
Collection是一个接口,里面定义了一组数据结构的操作,Java中的集合类都实现了这个接口。Collections是一个工具类,有一些常用的对集合的操作,比如toArray这些方法。
使用Arrays.asList获得的集合,不能对其进行增删改操作。asList返回的是一个Arrays的内部类对象,并没有实现增删改操作。该方法体现的是适配器模式,只是转换接口,实际上数据仍然是数组。