开篇寄语:HashSet底层是用Map来实现的,而HashMap底层就是用数组和链表来实现的。
查看HashSet源代码:
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<E,Object>();
}
在HashSet()底层,构造一个空的构造方法,这个方法体中会new一个HashMap();继续跟踪map定义.
private transient HashMap<E,Object> map;
HashSet底层会维护一个HashMap类型的 map对象。查看构造方法看不出所以然来,继续跟踪add()方法,查看添加元素时候的情况。 public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
如果put增加内容为空,则返回真。其中e表示往Set中增加的对象,PRESENT表示一个常量,
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
[一个假的值关联到这个对象上,再底层Map中]【说明】:从这边可以发现,当我们往Set中增加一个值的时候,这个值是存在Map中的key上面,value是一个常量,当增加第二值的时候,此时value同样是一个常量,value都是同一个对象。所以这边的Map仅仅是用到它的key,而value对它来说是无意义的。但是Map是有[key, value]所构成的所以必须要用。
1. HashSet底层是使用HashMap实现的。当使用add方法将对象添加到Set当中时,实际上是将该对象作为底层所维护的Map对象的key,而value则都是同一个Object对象(该对象我们用不上)。
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
public void clear() {
map.clear();
}
public int size() {
return map.size();
}
public Iterator<E> iterator() {
return map.keySet().iterator();
}
查看HashSet中源代码 remove(),clear(),size(),iterator()等方法返回的都是map中这些方法,其实 iterator()方法返回:return map.keySet().iterator();是利用keySet()方法键值取出再迭代。这就是HashSet底层的实现与map是紧密相关的。现在我们来看一下HashMap的底层实现方式。
HashMap源代码剖析:
查看其构造方法:
/**
* Constructs an empty <tt>HashMap</tt> with the default initial capacity
* (16) and the default load factor (0.75).
*/
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);