容器:Collection & Map
容器:Collection & Map
Collection 接口:
最基本的集合接口,一个 Collection 代表一组 Objects
不唯一,无序
List接口:
列表,通过索引访问元素
有序,不唯一
实例:
- ArrayList:底层用数组实现
- LinkedList:链表实现
List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。
Set接口:
不保存重复的元素
唯一,无序
Set几乎都是内部用一个Map来实现, 因为Map里的KeySet就是一个Set,而value是假值,全部使用同一个Object。Set的特征也继承了那些内部Map实现的特征。
判断重复:equals()
关于HashCode:
- 同一个对象必须始终返回相同的hashCode
- 两个对象的equals返回true,返回的hashCode也必须相同
- 两个对象不相等,也可能返回相同hashCode
实例:
- HashSet:无序,内部是一个HashMap,允许包含值为null的元素
- LinkedHashSet:有序,双向链表实现
- TreeSet:内部是TreeMap的SortedSet,可实现排序
Map 接口:
存储一组键值对象,k:v 映射
实例:
- HashMap:Entry[]
HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。
以Entry[]数组实现的哈希桶数组,用Key的哈希值取模桶数组的大小可得到数组下标。
- TreeMap:红黑树,元素默认按照keys的自然排序排列
- LinkedHashMap:扩展HashMap增加双向链表的实现,key有序
- 好像还有几个。。。。
Map.Entry
描述在一个Map中的一个元素(键/值对)。是一个Map的内部类。
关于红黑树,可参考:
- https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md
- https://mp.weixin.qq.com/s/jz1ajDUygZ7sXLQFHyfjWA
关于HashMap:
扩容:
Put() 函数
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
resize() 函数
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
//创建一个更大的
线程不安全
ConcurrentHashMap线程安全的。。
HashMap在JDK7+后 链表 ->红黑树
死循环问题:
扩容导致变成死循环列表
key 和 keyset()是同一组数据
有关于 map.entrySet() 和 keySet():
-
如果遍历 hashMap() 时 entrySet() 方法是将 key 和 value 全部取出来,所以性能开销是可以预计的, 而 keySet() 方法进行遍历的时候是根据取出的 key 值去查询对应的 value 值, 所以如果 key 值是比较简单的结构(如 1,2,3...)的话性能消耗上是比 entrySet() 方法低, 但随着 key 值得复杂度提高 entrySet() 的优势就会显露出来。
-
综合比较在只遍历 key 的时候使用 keySet(), 在只遍历 value 的是使用 values() 方法, 在遍历 key-value 的时候使用 entrySet() 是比较合理的选择。
-
如果遍历 TreeMap 的时候, 不同于 HashMap 在遍历 ThreeMap 的 key-value 时候务必使用 entrySet() 它要远远高于其他两个的性能, 同样只遍历 key 的时候使用 keySet(), 在只遍历 value 的是使用 values() 方法对于 TreeMap 也同样适用。
Guava ?
https://github.com/google/guava

浙公网安备 33010602011771号