WeakHashMap类实现了Map接口
public class WeakHashMap<K,V>extends AbstractMap<K,V>implements Map<K,V>
与其他Map实现类不同的是,WeakHashMap类的键对象间接地存储为一个弱引用的指示对象,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除。
引用的分类:
1.StrongReference 强引用 ,引用指向对象 ,gc运行时不回收
2.SoftReference 软引用,gc运行时可能会回收,比如当jvm内存不够时,就会回收
3.WeakReference 弱引用,gc运行时立即回收
4.PhantomReference 虚引用,类似于无引用,主要跟踪对象被回收的状态,不能单独使用,必须与引用队列(ReferenceQueue)联合使用
这里主要介绍弱引用:
当调用gc时,gc会回收对象,需要注意的是,它不会回收常量字符串,因为它是放在常量池中被共享的,所以即使断开引用gc也不会删除它,见代码:
import java.lang.ref.WeakReference;
public class Test {
public static void main(String[] args){
//字符串常量池
String str="hello world";
WeakReference<String> wr=new WeakReference<String>(str);
//断开引用
str=null;
//通知gc回收
System.gc();
System.runFinalization();
System.out.println(wr.get());
}
}
输出结果是 hello world
import java.lang.ref.WeakReference;
public class Test {
public static void main(String[] args){
//String对象
String str2=new String("hello again");
WeakReference<String> wr=new WeakReference<String>(str2);
str2=null;
System.gc();
System.runFinalization();
System.out.println(wr.get());
}
}
输出结果是 null
WeakHashMap类
import java.util.WeakHashMap;
public class Test {
public static void main(String[] args){
WeakHashMap<String,String> map=new WeakHashMap<String,String>();
//放入测试数据
map.put("1", "abc");
map.put(new String("2"), "qaz");
System.out.println(map.size());//输出结果为2
//运行垃圾回收
System.gc();
System.runFinalization();
System.out.println(map.size());//输出结果为1
}
}
new String(“2”)这个key值,以及它对应的value值都被删除了 ,所以map.size()为1
WeakHashMap的好处就在这里,如果你HashMap中的数据非常大,占用了大量的内存,你希望在gc运行时可以清理这些内存,就可以用WeakHashMap,而Map其他实现类都不可以实现这一点
IdentityHashMap类
此类利用哈希表实现 Map 接口,比较键(和值)时使用引用相等性代替对象相等性。也就是,在 IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等,而在正常 Map 实现类(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2)))。
import java.util.IdentityHashMap;
public class Test {
public static void main(String[] args){
IdentityHashMap<String,String> map=new IdentityHashMap<String,String>();
map.put("a", "qaz");
map.put("a", "wsx");
System.out.println(map.size());//输出结果为 1
map.put(new String("a"), "edc");
map.put(new String("a"), "rfv");
System.out.println(map.size());//输出结果为 3
}
}
这里的字符串常量“a”,是同一块内存地址,所以key相同,而每次new String(“a”),都创建一个新的String对象,开辟新的内存地址,所以是不同的key
EnumMap类
EnumMap要求键值必须是枚举类型,枚举即常量的集合
import java.util.EnumMap;
public class Test {
public static void main(String[] args){
EnumMap<Season,String> map=new EnumMap<Season,String>(Season.class);
map.put(Season.SPRING, "春");
map.put(Season.SUMMER, "夏");
map.put(Season.AUTUMN, "秋");
map.put(Season.WINTER, "冬");
System.out.println(map.size());//输出结果为4
}
}
enum Season{
SPRING,SUMMER,AUTUMN,WINTER
}
EnumMap的key值不可以是其他的,比如我泛型设置为Integer,是会报错的