java集合

1 CopyOnWriteArrayList

每次修改这个ArrayList的话,会将数组重新拷贝一份进行修改。读的话,直接读即可。因此修改对读没有影响。这个适合于并发时读远大于写的场合。因为拷贝数据耗内存。

读的时候不可以修改数据。CopyOnWriteArraySet是建立在CopyOnWriteArrayList上的。

2 HashMap

使用iterator遍历的时候,LinkedHashMap返回的序列的顺序和插入的顺序是一样的,而HashMap和TreeMap就不一定了。

LinkedHashSet背后是LinkedHashMap。

LinkedHashMap是HashMap的子类,它重写了HashMap的newNode方法,并且维护了一个双向链表,它将新加的node加入自己的双向链表中。

 首先是一个数组构成的bin,hash之后先找到结点对应的bin,每个bin后面插入冲突的结点,如果bin的节点数不多的话,小于等于6,就直接用一个链表来依次存放所有冲突的结点,如果bin的节点数据超过6的话,就使用一棵红黑树来保存该bin上所有冲突的节点。

注意,hash值不是key本身,而是调用key对象的hashcode()方法得到的,在插入底层的hashtable和从hashtable中找该key-value pair都是使用的是该hash code,而不是key本身。hashcode是在native层实现的。

hash table中保存的node是key和value一起保存的。但是,在查找的时候,除了hashcode需要匹配之外,还需要node的key也匹配才能返回。

2.1 HashMap的load factor

load factor的定义:load factor = hash map中元素的大小/hash map所使用的数组的大小(即bin的数目)。

注意是bin的数目,不包括每个bin自己的链表或者红黑树。因为某个bin一旦有了链表或者红黑树,查找就不是O(1)了,我们用hash table的目的就是为了保证常数查找时间。

load factor太大的话,每个bin里面的元素就会很多,导致查找变慢。load factor太小的话,会浪费存储空间。所以,load factor的选择是一种权衡,在时间和空间上的一种权衡。默认是0.75。

在设置好了load factor之后,如果hash map元素的个数大于load factor * bin数,那么就要对bin数进行扩容,即重新分配hash map后面的数组,新数组是旧数组大小的两倍。

3 TreeMap

TreeSet本质上是TreeMap的特例。

TreeMap是由红黑树实现的。

Set的底层是由Map实现的,而Map主要有两类Map,HashMap和TreeMap。

TreeMap里面的key使用的是真的插入的key,插入时,比较key和root,小往左插,大往右插,查找时同理。

4 list

list分为两类,一类是链表实现的LinkedList,一类是数组实现的ArrayList。Deque是一样的。

所以,java set的基本数据结构是链表、数组、hash map和tree map。

5 ConcurrentHashMap

分成了多个段,每个段一把锁,这样就可以允许多个人同时对不同的段进行写操作。

6 PriorityQueue

底层是用heap实现的,记住heapify是从n/2取整往前逐个shiftdown的,然后整个数组就满足堆序性了。

原文地址:https://www.cnblogs.com/hustdc/p/8483544.html