Java中的WeakHashMap containsKey()方法
在Java中,WeakHashMap是一种非常有用的Map实现。它是一种弱引用的Map,可以存储键值对,但是只要键不再被引用,系统就会将其从Map中删除。这个功能非常有用,特别是在某些场景下,比如缓存中的数据,我们不希望它们一直占用内存而不被使用。
在使用WeakHashMap时,有一个常见的操作就是判断一个键是否已经存在于Map中。这个判断可以通过Map的containsKey()方法来实现。不过,由于WeakHashMap是一种弱引用的Map,它的containsKey()方法有一些特殊之处,需要我们理解清楚。
WeakHashMap简介
在介绍WeakHashMap的containsKey()方法之前,我们先简单介绍一下WeakHashMap。WeakHashMap是Java集合框架中的一种Map实现,它的作用和HashMap类似,都是用于存储键值对的。不同的是,WeakHashMap的键是弱引用的,也就是说,只要键不再被程序中的任何对象引用,系统就会将键从WeakHashMap中删除。
我们可以通过下面这个示例代码来理解WeakHashMap的使用方法:
import java.util.WeakHashMap;
public class WeakHashMapDemo {
public static void main(String[] args) {
// 1. 创建一个WeakHashMap
WeakHashMap<MyKey, String> weakHashMap = new WeakHashMap<>();
// 2. 创建一个MyKey对象作为键
MyKey key = new MyKey("key");
// 3. 将键值对存入WeakHashMap中
weakHashMap.put(key, "value");
// 4. 查找键值对
System.out.println(weakHashMap.containsKey(key));
// 5. 将key的引用设为null
key = null;
// 6. 再次查找键值对
System.gc();
System.out.println(weakHashMap.containsKey(key));
}
}
class MyKey {
private String key;
public MyKey(String key) {
this.key = key;
}
@Override
public int hashCode() {
return key.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MyKey) {
MyKey other = (MyKey) obj;
return this.key.equals(other.key);
}
return false;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("MyKey对象被垃圾回收了");
}
}
上面这个示例中,我们创建了一个WeakHashMap对象,然后创建了一个MyKey对象作为键,并将其存入WeakHashMap中。在将key的引用设为null后,我们手动调用了一次垃圾回收,并通过containsKey()方法来查找键值对是否存在。可以发现,由于key不再被任何对象引用,所以它被垃圾回收了,而WeakHashMap也相应地将这个键值对删除了。
WeakHashMap的containsKey()方法
在使用WeakHashMap时,我们常常需要判断某个键是否已经存在于Map中。这个判断可以通过Map的containsKey()方法来实现。不过,由于WeakHashMap是一种弱引用的Map,它的containsKey()方法有一些特殊之处。
当我们使用WeakHashMap的containsKey()方法判断某个键是否存在时,需要注意以下三点:
- 如果指定的键对象已经被垃圾回收了,系统会自动将其从Map中删除。此时,containsKey()方法会返回“false”。
- 如果指定的键对象还没有被垃圾回收,但是它的引用已经被其他对象清除了,系统会自动将其从Map中删除。此时,containsKey()方法会返回“false”。
- 如果指定的键对象仍然有其他对象引用,那么即使它已经超过了它的生命周期,系统也不会将其从Map中删除。此时,containsKey()方法会返回“true”。
下面,我们通过示例代码来演示上述三点:
import java.util.WeakHashMap;
public class WeakHashMapContainsKeyDemo {
public static void main(String[] args) {
// 1. 创建一个WeakHashMap
WeakHashMap<MyKey, String> weakHashMap = new WeakHashMap<>();
// 2. 创建两个MyKey对象
MyKey key1 = new MyKey("key1");
MyKey key2 = new MyKey("key2");
// 3. 将两个键值对存入WeakHashMap中
weakHashMap.put(key1, "value1");
weakHashMap.put(key2, "value2");
// 4. 查找键值对
System.out.println(weakHashMap.containsKey(key1)); // true
System.out.println(weakHashMap.containsKey(key2)); // true
// 5. 将key1的引用设为null,并手动调用垃圾回收
key1 = null;
System.gc();
// 6. 再次查找键值对
System.out.println(weakHashMap.containsKey(key1)); // false
System.out.println(weakHashMap.containsKey(key2)); // true
// 7. 将key2的引用设为null,并手动调用垃圾回收
key2 = null;
System.gc();
// 8. 再次查找键值对
System.out.println(weakHashMap.containsKey(key1)); // false
System.out.println(weakHashMap.containsKey(key2)); // false
// 9. 创建一个新的MyKey对象
MyKey key3 = new MyKey("key3");
// 10. 将key3的引用设为null,并手动调用垃圾回收
key3 = null;
System.gc();
// 11. 将一个新的键值对存入WeakHashMap中
weakHashMap.put(key3, "value3");
// 12. 再次查找键值对
System.out.println(weakHashMap.containsKey(key3)); // false
}
}
在上面这个示例中,我们创建了一个WeakHashMap对象,并向其中存入了两个键值对。然后,我们先通过containsKey()方法查找这两个键,可以发现它们都存在于Map中。
接着,我们将key1的引用设为null,手动调用了一次垃圾回收。此时,由于key1已经没有任何对象引用,它被垃圾回收了,并从Map中被删除。因此,containsKey(key1)返回“false”,而containsKey(key2)仍然返回“true”。
然后,我们将key2的引用设为null,并手动调用了一次垃圾回收。此时,由于key2已经没有任何对象引用,它被垃圾回收了,并从Map中被删除。因此,containsKey(key2)返回“false”。
最后,我们创建了一个新的MyKey对象,并向其中存入了一个新的键值对。然而,在存入Map之后,我们立即将key3的引用设为null,并手动调用了一次垃圾回收。此时,由于key3没有任何对象引用,没有被垃圾回收,但是缺失了其他对象的引用,也就意味着没有被存活下来,因此并没有被加入Map中。因此,containsKey(key3)返回“false”。
结论
在使用WeakHashMap时,我们需要注意containsKey()方法的特殊之处。因为WeakHashMap中的键是弱引用的,所以当键的引用被清除后,系统会自动将其从Map中删除。因此,在使用containsKey()方法查找键是否存在时,需要注意键的引用是否被其他对象清除,以免出现误删或误存的情况。