Java WeakHashMap 到底Weak在哪里,它真的很弱吗?WeakHashMap 的适用场景是什么,使用时需要注意些什么?弱引用和强引用对Java GC有什么不同影响?本文将给出清晰而简洁的介绍。
总体介绍
在Java集合框架系列文章的最后,笔者打算介绍一个特殊的成员:WeakHashMap,从名字可以看出它是某种 Map。它的特殊之处在于 WeakHashMap 里的entry
可能会被GC自动删除,即使程序员没有调用remove()
或者clear()
方法。
更直观的说,当使用 WeakHashMap 时,即使没有显示的添加或删除任何元素,也可能发生如下情况:
- 调用两次
size()
方法返回不同的值;- 两次调用
isEmpty()
方法,第一次返回false
,第二次返回true
;- 两次调用
containsKey()
方法,第一次返回true
,第二次返回false
,尽管两次使用的是同一个key
;- 两次调用
get()
方法,第一次返回一个value
,第二次返回null
,尽管两次使用的是同一个对象。
遇到这么奇葩的现象,你是不是觉得使用者一定会疯掉?其实不然,WeekHashMap 的这个特点特别适用于需要缓存的场景。在缓存场景下,由于内存是有限的,不能缓存所有对象;对象缓存命中可以提高系统效率,但缓存MISS也不会造成错误,因为可以通过计算重新得到。
要明白 WeekHashMap 的工作原理,还需要引入一个概念:弱引用(WeakReference)。我们都知道Java中内存是通过GC自动管理的,GC会在程序运行过程中自动判断哪些对象是可以被回收的,并在合适的时机进行内存释放。GC判断某个对象是否可被回收的依据是,是否有有效的引用指向该对象。如果没有有效引用指向该对象(基本意味着不存在访问该对象的方式),那么该对象就是可回收的。这里的“有效引用”并不包括弱引用。也就是说,虽然弱引用可以用来访问对象,但进行垃圾回收时弱引用并不会被考虑在内,仅有弱引用指向的对象仍然会被GC回收。
WeakHashMap 内部是通过弱引用来管理entry
的,弱引用的特性对应到 WeakHashMap 上意味着什么呢?将一对key, value
放入到 WeakHashMap 里并不能避免该key
值被GC回收,除非在 WeakHashMap 之外还有对该key
的强引用。
关于强引用,弱引用等概念以后再具体讲解,这里只需要知道Java中引用也是分种类的,并且不同种类的引用对GC的影响不同就够了。
具体实现
WeakHashMap的存储结构类似于HashMap,读者可自行参考前文,这里不再赘述。
关于强弱引用的管理方式,博主将会另开专题单独讲解。
Weak HashSet?
如果你看过前几篇关于 Map 和 Set 的讲解,一定会问:既然有 WeekHashMap,是否有 WeekHashSet 呢?答案是没有:( 。不过Java Collections工具类给出了解决方案,Collections.newSetFromMap(Map<E,Boolean> map)
方法可以将任何 Map包装成一个Set。通过如下方式可以快速得到一个 Weak HashSet:
Set<Object> weakHashSet = Collections.newSetFromMap(
new WeakHashMap<Object, Boolean>());
不出你所料,newSetFromMap()
方法只是对传入的 Map做了简单包装:
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
return new SetFromMap<>(map);
}
private static class SetFromMap<E> extends AbstractSet<E>
implements Set<E>, Serializable
{
private final Map<E, Boolean> m; // The backing map
private transient Set<E> s; // Its keySet
SetFromMap(Map<E, Boolean> map) {
if (!map.isEmpty())
throw new IllegalArgumentException("Map is non-empty");
m = map;
s = map.keySet();
}
public void clear() { m.clear(); }
public int size() { return m.size(); }
public boolean isEmpty() { return m.isEmpty(); }
public boolean contains(Object o) { return m.containsKey(o); }
public boolean remove(Object o) { return m.remove(o) != null; }
public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
public Iterator<E> iterator() { return s.iterator(); }
public Object[] toArray() { return s.toArray(); }
public <T> T[] toArray(T[] a) { return s.toArray(a); }
public String toString() { return s.toString(); }
public int hashCode() { return s.hashCode(); }
public boolean equals(Object o) { return o == this || s.equals(o); }
public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
public boolean removeAll(Collection<?> c) {return s.removeAll(c);}
public boolean retainAll(Collection<?> c) {return s.retainAll(c);}
// addAll is the only inherited implementation
}
相关推荐
WeakHashMap的使用方法详解 WeakHashMap是Java中的一种哈希映射表,它的键是弱引用的,意味着当 WeakHashMap 的键对象只有 WeakHashMap 自己持有时,垃圾回收器可以将其回收。WeakHashMap 的使用方法主要体现在...
WeakHashMap是Java中的一种特殊的哈希表实现,它使用弱引用(Weak Reference)来保存键对象。当键对象没有被其他强引用引用时,在垃圾回收时会自动从WeakHashMap中移除对应的键值对。
Java编程WeakHashMap实例解析 WeakHashMap是Java编程中的一种特殊的HashMap实现,它使用弱引用来保存键和值,这样可以使得垃圾回收器自动清理键和值。在WeakHashMap中,键和值都是弱引用的,这样可以避免内存泄露...
在Java编程中,WeakHashMap是一种特殊的哈希表,它的键(Key)是弱引用,当键被垃圾回收器清除后,即使有值(Value)存在,该条目也会自动从哈希表中移除。 线程死锁的原因通常包括以下几点: 1. **资源互斥**:每...
书中还提到可以用WeakHashMap来作为缓存的容器可以有效解决这一问题。之前也确实遇到过类似问题,但是没有接触过“弱引用”相关的问题,于是查阅了一些资料。 《Java 理论与实践: 用弱引用堵住内存泄漏》一文也...
- **expungeStaleEntries 方法**:为了确保 WeakHashMap 的键被正确清理,每当访问 WeakHashMap 的时候,都会调用 expungeStaleEntries 方法来清除已经无效的键值对。 #### 七、WeakHashMap 的局限性 - **访问触发...
这意味着如果键不再被任何对象引用,那么即使在 WeakHashMap 中,这个键也会被垃圾收集器回收。这种方式可以防止内存泄漏,但也可能导致数据丢失。 总结: - Vector 和 ArrayList 都实现了 List 接口,其中 Vector ...
WeakHashMap是一种特殊的哈希表,它使用弱引用作为键,当键不再被引用时,即使没有显式地从集合中移除,也会自动清理。 **Map接口** Map接口存储键值对,不直接继承自Collection接口。常见的Map实现有Hashtable、...
【描述】"Java-WeakIdentityHashMap.zip, weakhashmap identityhashmapa独立库的组合,用于weakidentityhashmap实现内/外字段" 描述的是一个特定的Java数据结构实现,即WeakIdentityHashMap。这是一个结合了...
WeakHashMap是Map接口的基于弱键的实现,以弱键实现的基于哈希表的Map。在WeakHashMap中,当某个键不再正常使用时,将自动移除其条目。 Java集合类提供了多种实现,用于解决不同的数据存储和操作问题。开发者可以...
而在`WeakHashMap`中,键是弱引用,当垃圾回收器回收了键所引用的对象,`WeakHashMap`会自动移除相应的键值对,从而允许垃圾回收。 最后,`IdentityHashMap`是一个特殊版本的哈希表,它使用对象的内存地址(`==`...
WeakHashMap是一种特殊的Map实现,它使用弱引用作为键,当键不再被引用时,即使在Map中,也会被垃圾回收器清除,从而释放内存资源。 总结来说,选择哪种容器取决于具体的需求:如果需要有序的元素集合,可以使用...
`WeakHashMap`使用弱引用作为键,当键不再被其他对象引用时,即使没有调用`remove`,键值对也会自动从`WeakHashMap`中消失,这是一种内存管理策略。 了解并熟练运用这些基础数据结构和集合框架,对于提升开发效率和...
什么是 Java2 Java 的特点Java 开发环境 JDK JRE Java 开发环境配置 Java 基本语法 数据类型基础语法运算符 Java 执行控制流程条件语句 if 条件语句 if...else 条件语句if...else if 多分支语句switch 多分支语句 ...
这意味着当没有强引用指向这些键时,垃圾回收器可以回收它们,即使它们仍然存在于`WeakHashMap`中。这使得`WeakHashMap`非常适合用于缓存场景,其中键可能不再被程序的其他部分使用。 总之,Java集合框架提供了一...
Map接口包括HashMap、TreeMap、WeakHashMap等实现类,它们各自有各自的特性和适用场景。 例如,HashMap是基于哈希表实现的,提供快速的插入、删除和查找操作,平均时间复杂度为O(1)。而TreeMap则基于红黑树,它保持...
3. Map接口:Map用于存储键值对,HashMap、HashTable、TreeMap和WeakHashMap等是其实现。HashMap提供非同步的快速查找,HashMap的长度通常是2的幂次方,以优化哈希分布。HashTable是线程安全的,但效率较低。TreeMap...
LinkedHashMap保持了元素的插入顺序,WeakHashMap允许弱引用键,当键不再被引用时,键值对会自动移除。IdentityHashMap使用对象的引用相等性作为判断键是否相同的依据,而非equals()方法的返回值。 在性能方面,...
- **WeakHashMap**和**IdentityHashMap**:特殊类型的Map,WeakHashMap的键使用弱引用,键在不再被引用时会被自动清理;IdentityHashMap使用对象的引用地址而非equals()方法来判断键的相等性。 4. **关联操作** -...