HashSet 与 LinkedHashSet
HashSet 和 LinkedHashSet 是对 HashMap 和 LinkedHashMap 的简单包装,对 HashSet 的函数调用都会转换成合适的 HashMap 方法。LinkedHashSet 的函数会转换成合适的 LinkedHashMap 的方法。
//HashSet是对HashMap的简单包装
public class HashSet<E>
{
......
private transient HashMap<E,Object> map;//HashSet里面有一个HashMap
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
......
public boolean add(E e) {//简单的方法转换
return map.put(e, PRESENT)==null;
}
......
}
WeakHashMap
这个 Map 比较特殊,特殊之处在于 WeakHashMap 里的 entry 可能会被 GC 自动删除,即使程序员没有调用 remove 或者 clear 方法。
更为直观的说,当使用 WeakHashMap 时,即使没有显示的添加或者删除元素,也可能发生如下情况:
调用两次 size() 返回不同的值。
两次调用 isEmpty() 方法,第一次返回 false,第二次返回 true。
两次调用 containsKey() 方法,第一次返回 true,第二次返回 false。
两次调用 get() 方法,第一次返回一个 value,第二次返回 null。
WeakHashMap 的这个特点特别适用于需要缓存的场景。在缓存场景下,由于内存是有限的,不能缓存所有对象;对象缓存命中可以提高系统效率,但缓存MISS也不会造成错误,因为可以通过计算重新得到。
WeakHashMap 的核心是弱引用(WeakReference)。我们都知道内存是通过 GC 自动管理的,GC 会在程序运行中自动判断哪些对象是可回收的,并在合适的时机进行内存释放。GC 判断某个对象是否可被回收的依据是,是否有有效的引用指向该对象。如果没有有效引用直线该对象,那么该对象就是可回收的。
虽然弱引用可以用来访问对象,但进行垃圾回收时弱引用并不会被考虑在内,仅有弱引用指向 的对象仍然会被 GC 回收。