一.HashMap
1.HashMap是基于Key-Value的散列表(JDK7:数组+链表,JDK8:数组+链表+红黑树),采用拉链法实现的。一般用于单线程当中,非线程安全,HashMap的键是"强键"。
2.继承于抽象类AbstractMap,并且实现Map接口。遍历时,取得的数据完全是随机的。
3.默认容量大小是16,加载因子是0.75。
4.最多只允许一条key为Null,允许多条value为Null。
5.HashMap实现了Cloneable和Serializable接口,而WeakHashMap没有。
1).HashMap实现Cloneable,说明它能通过clone()克隆自己。
2).HashMap实现Serializable,说明它支持序列化,能通过序列化去传输。
6.添加、删除操作时间复杂度都是O(1)。
二.weakHashMap
1.weakHashMap是基于Key-Value的散列表(数组+链表),采用拉链法实现的。一般用于单线程当中,非线程安全,weakHashMap中的键是"弱键"。
备注:当"弱键"被GC会收时,它对应的键值也会从weakHashMap中删除。
2.继承于抽象类AbstractMap,并且实现Map接口。
3.默认容量大小是16,加载因子是0.75。
4.最多只允许一条key为Null,允许多条value为Null。
weakhashmap继承:猜测是因为“xxx”形式时,会首先从字符串静态池中获取。当获取不到时。会new一个放入静态池。调用。
它的生存周期是到方法体结束,在你的输出代码后面。而其他两个都是匿名对象,生存周期是在map的生存周期里,map都回收了自然也被回收了。
UML结构图:
(1) 抽象享元角色:为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。在Java中可以由抽象类、接口来担当。
(2) 具体享元角色:实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
(3) 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!
(4) 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
一、Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。Map接口定义了如下常用的方法:
1、void clear():删除Map中所以键值对。
2、boolean containsKey(Object key):查询Map中是否包含指定key,如果包含则返回true。
3、boolean containsValue(Object value):查询Map中是否包含指定value,如果包含则返回true。
4、Set entrySet():返回Map中所包含的键值对所组成的Set集合,每个集合元素都是Map.Entry对象(Entry是Map的内部类)。
5、Object get(Object key):返回指定key所对应的value,如Map中不包含key则返回null。
6、boolean isEmpty():查询Map是否为空,如果空则返回true。
7、Set keySet():返回该Map中所有key所组成的set集合。
8、Object put(Object key,Object value):添加一个键值对,如果已有一个相同的key值则新的键值对覆盖旧的键值对。
9、void putAll(Map m):将指定Map中的键值对复制到Map中。
10、Object remove(Object key):删除指定key所对应的键值对,返回可以所关联的value,如果key不存在,返回null。
11、int size():返回该Map里的键值对的个数。
12、Collection values():返回该Map里所有value组成的Collection。
Map中包含一个内部类:Entry。该类封装了一个键值对,它包含了三个方法:
1、Object getKey():返回该Entry里包含的key值。
2、Object getValeu():返回该Entry里包含的value值。
3、Object setValue(V value):设置该Entry里包含的value值,并返回新设置的value值。
二、HashMap和Hashtable实现类:
1、HashMap与HashTable的区别:
1) 同步性:Hashtable是同步的,这个类中的一些方法保证了Hashtable中的对象是线程安全的。而HashMap则是异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。
2) 值:HashMap可以让你将空值作为一个表的条目的key或value,但是Hashtable是不能放入空值的。HashMap最多只有一个key值为null,但可以有无数多个value值为null。
2、性能:HashMap的性能最好,HashTable的性能是最差(因为它是同步的)
3、注意:
1)用作key的对象必须实现hashCode和equals方法。
2)不能保证其中的键值对的顺序。
3)尽量不要使用可变对象作为它们的key值。
三、LinkedHashMap:
它的父类是HashMap,使用双向链表来维护键值对的次序,迭代顺序与键值对的插入顺序保持一致。LinkedHashMap需要维护元素的插入顺序,so性能略低于HashMap,但在迭代访问元素时有很好的性能,因为它是以链表来维护内部顺序。
四、TreeMap:
Map接口派生了一个SortMap子接口,SortMap的实现类为TreeMap。TreeMap也是基于红黑树对所有的key进行排序,有两种排序方式:自然排序和定制排序。Treemap的key以TreeSet的形式存储,对key的要求与TreeSet对元素的要求基本一致。
1、Map.Entry firstEntry():返回最小key所对应的键值对,如Map为空,则返回null。
2、Object firstKey():返回最小key,如果为空,则返回null。
3、Map.Entry lastEntry():返回最大key所对应的键值对,如Map为空,则返回null。
4、Object lastKey():返回最大key,如果为空,则返回null。
5、Map.Entry higherEntry(Object key):返回位于key后一位的键值对,如果为空,则返回null。
6、Map.Entry lowerEntry(Object key):返回位于key前一位的键值对,如果为空,则返回null。
7、Object lowerKey(Object key):返回位于key前一位key值,如果为空,则返回null。
8、NavigableMap subMap(Object fromKey,boolean fromlnclusive,Object toKey,boolean toInciusive):返回该Map的子Map,其key范围从fromKey到toKey。
9、SortMap subMap(Object fromKey,Object toKey );返回该Map的子Map,其key范围从fromkey(包括)到tokey(不包括)。
10、SortMap tailMap(Object fromkey ,boolean inclusive):返回该Map的子Map,其key范围大于fromkey(是否包括取决于第二个参数)的所有key。
11、 SortMap headMap(Object tokey ,boolean inclusive):返回该Map的子Map,其key范围小于tokey(是否包括取决于第二个参数)的所有key。
五、WeakHashMap:
WeakHashMap与HashMap的用法基本相同,区别在于:后者的key保留对象的强引用,即只要HashMap对象不被销毁,其对象所有key所引用的对象不会被垃圾回收,HashMap也不会自动删除这些key所对应的键值对对象。但WeakHashMap的key所引用的对象没有被其他强引用变量所引用,则这些key所引用的对象可能被回收。WeakHashMap中的每个key对象保存了实际对象的弱引用,当回收了该key所对应的实际对象后,WeakHashMap会自动删除该key所对应的键值对。
六、IdentityHashMap类:
IdentityHashMap与HashMap基本相似,只是当两个key严格相等时,即key1==key2时,它才认为两个key是相等的 。IdentityHashMap也允许使用null,但不保证键值对之间的顺序。
七、EnumMap类:
1、EnumMap中所有key都必须是单个枚举类的枚举值,创建EnumMap时必须显示或隐式指定它对应的枚举类。
2、EnumMap根据key的自然顺序,即枚举值在枚举类中定义的顺序,来维护键值对的次序。
3、EnumMap不允许使用null作为key值,但value可以。望采纳,谢谢。
Map有:HashMap、TreeMap、Hashtable。
1、HashMap:线程不安全,键、值不允许为null,并且没顺序。
2、Hashtable:线程安全,键、值允许为null,并且没顺序。
3、TreeMap:线程不安全、键、值不允许为null,并且没顺序。
备注:当前用的最多的是HashMap,因为线性不安全,也就是说读取和存储效率要更高一些。
很早Java API就添加了弱引用(WeakReference)和软引用(SoftReference),引用类在垃圾回收工作的过程中有重要作用。我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型。
这正是Java中弱引用和软引用的主要区别。如果一个对象只有弱引用指向它,垃圾回收器会立即回收该对象,这是一种急切回收方式。相对的,如果有软引用指向这些对象,则只有在JVM需要内存时才回收这些对象。弱引用和软引用的特殊行为使得它们在某些情况下非常有用。例如:软引用可以很好的用来实现缓存,当JVM需要内存时,垃圾回收器就会回收这些只有被软引用指向的对象。而弱引用非常适合存储元数据,例如:存储ClassLoader引用。
如果有类被加载,那么也没有指向ClassLoader的引用。一旦上一次的强引用被去除,只有弱引用的ClassLoader就会被回收。
Java中弱引用VS软引用
Java中有如下四种类型的引用:
强引用(Strong Reference)。
弱引用(WeakReference)。
软引用(SoftReference)。
虚引用(PhantomReference)。
强引用是我们在编程过程中使用的最简单的引用,如代码String s=”abc”中变量s就是字符串对象”abc”的一个强引用。任何被强引用指向的对象都不能被垃圾回收器回收,这些对象都是在程序中需要的。弱引用使用java.lang.ref.WeakReference class 类来表示,你可以使用如下代码创建弱引用:
代码如下:
Counter counter = new Counter(); // strong reference - line 1。
WeakReference<Counter> weakCounter = new WeakReference<Counter>(counter);。
//weak reference。
counter = null; // now Counter object is eligible for garbage collection。
现在只要你给强引用对象counter赋空值null,该对象就可以被垃圾回收器回收。因为该对象此时不再含有其他强引用,即使指向该对象的弱引用weakCounter也无法阻止垃圾回收器对该对象的回收。相反的,如果该对象含有软引用,Counter对象不会立即被回收,除非JVM需要内存。Java中的软引用使用java.lang.ref.SoftReference类来表示,你可以使用如下代码创建软引用:
代码如下:
Counter prime = new Counter(); // prime holds a strong reference _ line 2。
SoftReference soft = new SoftReference(prime) ; //soft reference variable has。
SoftReference to Counter Object created at line 2。
prime = null; // now Counter object is eligible for garbage collection but only be。
collected when JVM absolutely needs memory。
强引用置空之后,代码的第二行为对象Counter创建了一个软引用,该引用同样不能阻止垃圾回收器回收对象,但是可以延迟回收,与弱引用中急切回收对象不同。鉴于软引用和弱引用的这一区别,软引用更适用于缓存机制,而弱引用更适用于存贮元数据。另一个使用弱引用的例子是WeakHashMap,它是除HashMap和TreeMap之外,Map接口的另一种实现。
WeakHashMap有一个特点:map中的键值(keys)都被封装成弱引用,也就是说一旦强引用被删除,WeakHashMap内部的弱引用就无法阻止该对象被垃圾回收器回收。
虚引用是java.lang.ref package包中第三种可用的引用,使java.lang.ref.PhantomReference类来表示。拥有虚引用的对象可以在任何时候被垃圾回收器回收。和弱引用和软引用相似,你可以通过如下代码创建虚引用:
代码如下:
DigitalCounter digit = new DigitalCounter(); // digit reference variable has strong。
reference _ line 3。
PhantomReference phantom = new PhantomReference(digit); // phantom reference to object created at line 3。
digit = null;
一旦移除强引用,第三行的DigitalCounter对象可以在任何时候被垃圾回收器回收。因为只有一个虚引用指向该对象,而虚引用无法阻止垃圾回收器回收对象。
除了了解弱引用、软引用、虚引用和WeakHashMap,还需要了解ReferenceQueue。在创建任何弱引用、软引用和虚引用的过程中你可以通过如下代码提供引用队列ReferenceQueue:
代码如下:
ReferenceQueue refQueue = new ReferenceQueue(); //reference will be stored in this queue for cleanup。
DigitalCounter digit = new DigitalCounter();。
PhantomReference<DigitalCounter> phantom = new。
PhantomReference<DigitalCounter>(digit, refQueue);。
引用实例被添加在引用队列中,你可以再任何时候通过查询引用队列回收对象。一个对象的生命周期可以通过下图进行描述:
在新窗口打开图片
这就是Java中弱引用和软引用的区别。我们还学到了一些基本的引用类:弱引用、软引用、虚引用以及WeakHashMap和WeakHashMap。总之,合理的使用引用可以帮助垃圾回收器更好的管理Java内存。