jdk 源码阅读简单记录。
java.util
ArrayList
注释表明 ArrayList 允许 null 值,大致功能与 Vector 相同,只是是非线程安全的。
ArrayList 内部本身维护了一个 Object 数组来完成数据的存储。
需要注意的是,ArrayList 的 clone 方法并不能复制一个新对象,有如下代码:
1 | ArrayList<SomeEntity> list = new ArrayList<>(); |
程序运行后输出如下
1 | true |
可见 clone() 方法不能复制一个 ArrayList。
LInkedList
注释表明内部维护了双向链表,同时允许 null 值作为元素,非线程安全。如果想要在多线程下使用,可以使用如下代码:
1 | List list = Collections.synchronizedList(new ArrayList()); |
HashMap
简单摘录注释如下
1 | permits `null` values and the `null` key. The <tt>HashMap</tt> class is roughly equivalent to <tt>Hashtable</tt>, except that it is unsynchronized and permits nulls. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is <i>rehashed</i> (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets. |
其中rehash的作用是扩容,在hashmap中已经更名为 resize()
,而hashtable中仍旧为 rehash()
。简单对比了 hashmap 与 hashtale 后发现,hashmap的由于hash操作更加合理,冲突处理更加好,所以现在更加推荐使用hashmap;而并发情况下使用hashtable效率也不高,通常更推荐使用 concurrentHashmap。
hashmap的原理大致如下:hashmap维护了一个数组,当向hashmap中添加元素时,首先计算key值的hash,并通过计算转换为数组中的下标,如果对应的位置为空,则放入位置;否则在对应的位置处使用链表,将元素添加到链表的尾部;当链表长度大于设定的值时,将链表转换为查找速度更快的红黑树。
对于hashmap,最常用的方法就是put() 与get() 了。对于put() 方法,源码中只是直接调用了putval方法,所以摘录putVal() 方法如下,同时添加注释:
1 | final V putVal(int hash, K key, V value, boolean onlyIfAbsent, |
get()方法同样是调用了getNode()方法,在获取到节点后返回节点的value。以下为getNode()方法:
1 | final Node<K,V> getNode(int hash, Object key) { |
对于hashmap,影响其容量大小的有两个成员变量:loadfactor与capacity。loadfactor是扩容系数,当当前hashmap的容量达到 loadfactor * capacity时,hashmap会进行扩容,容量翻倍。
HashSet
通过查看源码可以知道,java的HashSet是基于HashMap实现的。HashSet内部持有一个HashMap实例map,map的key作为set的元素,map的value被设置为new Object()。
LinkedHashMap
增加了双向链表结构的HashMap,本身也是基于HashMap实现的,多用于LRU。
Vector
相当于可变容量的数组,同时每个方法都有synchronized修饰,支持多线程同时并发效率也比较低。
TreeMap
TreeMap源码使用红黑树实现,代码比较复杂,可以参考这篇文章
Collections
主要为Collection下的类提供一些操作方法,下面是一些日常可能会用到的:
1 | public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)//list的二分查找 |
Arrays
提供数组的一些操作方法,例如排序、查找、填充等。其中有一个方法是 asList(T... a)
,返回一个List对象,但是这个对象的类是Arrays的子类并不是ArrayList。