Arraylist
数组结构。特点查询快,不适合对结构的前中部位,进行大量插入,删除操作,因为会造成数组元素大量迁移。线程不安全,若要线程安全建议用CopyOnWriteArrayList。
LinkedList
双向链表结构。本身实现Deque接口,队列结构。适用于频繁改变集合结构。比如对结构所有部位的插入,删除等。由于双向链表结构特点,对于结构中间部位的操作,内部需要遍历较长距离,较为耗时。线程不安全,线程安全可用ConcurrentLinkedDeque。
HashMap
数组加链表的结构,key的对象必须实现equals与hashcode的函数,其中equals方法是为了防止产生hash冲突,如果多个key哈希一致,如果没有达到扩容的条件,先是组建链表,插入到key对应数组位置的链表尾部,在Java8中,如果链表过长,则会生成一颗红黑树。
扩容中,会重新构建内部结构,这个过程是比较耗时的,所以合适的集合容量很重要。由于内部设计采用位操作来计算hash值对于的位置,实际上最大容量会是,比如16,32,64。
线程不安全,线程安全建议用ConcurrentHashMap。
LinkedHashMap
继承HashMap,保持插入顺序。AccessOrder为true时,被访问的元素放到最尾部,为false时保留原来的插入顺序。
比HashMap多维护一个双向链表。遍历时直接使用此链表。非线程安全。
WeakHashMap
弱引用,其中的Entry(继承WeakReference)只能存活到下一次垃圾回收前,一般用在缓存设计。
TreeMap
基于红黑树的实现,是有序结构,默认new对象时没有传入Comparator则按照Comparable接口提供的方法否则用传入的Comparator进行大小判断。非线程安全,如果要线程安全,其中一个方法是,用Collections. synchronizedSortedMap处理该对象,返回SortedMap。
HashSet
内部使用了HashMap,只使用了Key,把key单做HashMap的key,其中使用预生成的Object对象当做所有key的value。注意key需要实现,hashcode与equals函数。
CopyOnWriteArrayList
每次添加一个值时,开启锁,先新建一个数组B,然后复制缓存中的数组A到这个数组B,然后对这个新数组B进行添加操作,而后重新设置list的缓存数组为B,解锁。同时使得每次get,for操作都是对过去缓存A进行操作。修改操作与上类似,以此达到线程安全的目的。
对于迭代次数远远大于修改次数时,应当用此类,相反时,由于每次修改将会生成新的数组来替换,所以应当用Collections.synchronizedList()生成的线程安全List。
线程安全的处理:
在没有可用替代类的情况下,可以自己通过组合或则继承(建议组合,减少不必要的非线程安全方法的暴露)的方式,构造线程安全的方法,或则通过Collections.synchronize*() 方法的生成新对象。由于synchronize*对方法的锁范围大,建议尽量用替代类。