Map提供了一个更通用的元素存储方法。Map集合类用于存储元素对(成为键值对),其中每个键映射一个值。
1. HashMap
最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap 最多允许一条记录的键为Null(多条会覆盖 其实不为Null 的其他key值也不能重复);允许多条记录的值为Null 。非同步的。
2. HashTable
与HashMap 类似 不同的是key和value的值不允许为null,它支持线程的同步,即任一时刻只有一个线程能写HashTable,这也导致了HashTable写入的时候比较慢!是很慢,新版本jdk不用他了 用ConcurrentHashMap代替
3.Proreties
import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.util.Iterator;import java.util.Properties;import java.util.Map.Entry;/** * 对属性文件操作的工具类 * 获取,新增,修改 * 注意: 以下方法读取属性文件会缓存问题,在修改属性文件时,不起作用, * InputStream in = PropertiesUtils.class.getResourceAsStream("/config.properties"); * 解决办法: * String savePath = PropertiesUtils.class.getResource("/config.properties").getPath(); * @author sdj */public class PropertiesUtils {/** * 获取属性文件的数据 根据key获取值 * @param fileName 文件名 (注意:加载的是src下的文件,如果在某个包下.请把包名加上) * @param key * @return */public static String findPropertiesKey(String key) {try { Properties prop = getProperties();return prop.getProperty(key);} catch (Exception e) {return "";}}public static void main(String[] args) { Properties prop = new Properties(); InputStream in = PropertiesUtils.class.getResourceAsStream("/config.properties");try { prop.load(in); Iterator<Entry<Object, Object>> itr = prop.entrySet().iterator();while (itr.hasNext()) { Entry<Object, Object> e = (Entry<Object, Object>) itr.next(); System.err.println((e.getKey().toString() + "" + e.getValue().toString()));}} catch (Exception e) {}}/** * 返回 Properties * @param fileName 文件名 (注意:加载的是src下的文件,如果在某个包下.请把包名加上) * @param * @return */public static Properties getProperties(){ Properties prop = new Properties(); String savePath = PropertiesUtils.class.getResource("/config.properties").getPath();//以下方法读取属性文件会缓存问题// InputStream in = PropertiesUtils.class// .getResourceAsStream("/config.properties");try { InputStream in =new BufferedInputStream(new FileInputStream(savePath)); prop.load(in);} catch (Exception e) {return null;}return prop;}/** * 写入properties信息 * * @param key * 名称 * @param value * 值 */public static void modifyProperties(String key, String value) {try {// 从输入流中读取属性列表(键和元素对) Properties prop = getProperties(); prop.setProperty(key, value); String path = PropertiesUtils.class.getResource("/config.properties").getPath(); FileOutputStream outputFile = new FileOutputStream(path); prop.store(outputFile, "modify"); outputFile.close(); outputFile.flush();} catch (Exception e) {}}}
4.LinkedHashMap
保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,在遍历的时候比HashMap慢,key value 均允许为null ,非同步的
5.IdentituHashMap
他与HashMap唯一的不同之处是,他的key值允许重复,但是key必须是两个不同的对象,也就是说k1和k2 当 k1 == k2 时,IdentityHashMap 认为两个Key相等,而HashMap只有在k1.equals(k20) == true 时 就会认为两个key相等
6.TreeMap
package along;import java.util.HashMap;import java.util.IdentityHashMap;public class Test2 { public static void main(String[] args) { IdentityHashMap<String,String> im = new IdentityHashMap<String,String>(); HashMap<String,String> hm = new HashMap<String,String>(); String key1 = new String("ceshi"); String key2 = new String("ceshi"); System.out.println(key1 == key2);//false System.out.println(key1.equals(key2));//true im.put(key1, "测试"); im.put(key2, "测试2"); hm.put(key1, "测试"); hm.put(key2, "测试2"); System.out.println(im);//{ceshi=测试, ceshi=测试2} System.out.println(hm);//{ceshi=测试2} }}
7.WeakHashMap
- 和HashMap一样,也是一个散列表,它存储的内容也是键值对,而且键和值都可以是null
- 不是同步的 但是Java提供同步方式
Collections.synchronizedMap(new WeakHashMap<>());
不过WeakHashMap的键是弱键,
在WebkHashMap中,当某个键不再正常使用时,会被从WeakHashMap中被自动移除。
更精确的说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收,某个键被终止时,它对应的键值对也就从映射中移除了
这个弱键的原理是通过WeakReference和ReferenceQueue实现的。WeakHashMap 的key是弱键,即是WeakReference类型的;ReferenceQueue是一个队列,它会保存被GC回收的弱键。
弱键如何被自动从WeakHashMap中删除的步骤
1)新建WeakHashMap 将键值对添加到WeakHashMap中
实际上,WeakHashMap 是通过数组table保存Entry(键值对) ;每一个Entry实际上是一个单向链表,即Entry是键值对链表。
2)当某个弱键不再被其它对象引用,并被GC回收时,在GC回收该弱键时,这个弱键也同时被添加到ReferenceQueue队列中。
3)当下一次我们需要操作WeakHashMap时,会先同步table和queue,table中保存了全部的键值对,而queue中保存了被GC回收的键值对;同步他们就是删除table中被GC回收的键值对
package along;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import java.util.WeakHashMap;/** * WeakHashMap实例 */public class Test2 { public static void main(String[] args) throws Exception { // 初始化3个“弱键” 不被引用的时候就成了弱键(比如w1 = null; w1就成了弱键) String w1 = new String("one"); String w2 = new String("two"); String w3 = new String("three"); // 新建WeakHashMap Map<String,String> wmap = new WeakHashMap<String,String>(); // 添加键值对 wmap.put(w1, "w1"); wmap.put(w2, "w2"); wmap.put(w3, "w3"); // 打印出wmap内容 System.out.printf("\n原始 wmap:%s\n",wmap ); // containsKey(Object key) :是否包含键key System.out.printf("包含key => two : %s\n",wmap.containsKey("two")); System.out.printf("包含key => five : %s\n",wmap.containsKey("five")); // containsValue(Object value) :是否包含值value System.out.printf("包含值 => w1 : %s\n",wmap.containsValue("w1")); // remove(Object key) : 删除键key对应的键值对 wmap.remove("three");// wmap.remove(w3); 也一样 System.out.printf("删除three 的 wmap: %s\n",wmap ); // ---- 测试 WeakHashMap 的自动回收特性 ---- // 将w1设置null。 // 这意味着“弱键”w1再没有被其它对象引用,调用gc时会回收WeakHashMap中与“w1”对应的键值对 w1 = null; // 内存回收。这里,会回收WeakHashMap中与“w1”对应的键值对 System.gc(); // 遍历WeakHashMap Iterator<Entry<String, String>> iter = wmap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String, String> en = iter.next(); System.out.printf("next : %s - %s\n",en.getKey(),en.getValue()); } // 打印WeakHashMap three被删除了 one 被回收了 System.out.printf("gc 后的wmap :%s\n", wmap); }}
8.ConcurrentHashMap
推荐看一篇文章 很受用
专用Map 通常我们不需要亲自创建这类map 而是通过某些其他类对其进行访问
java.util.jar.Attributes javax.print.attribute.standard.PrinterStateReasons
java.security.Provider java.awt.RenderingHints javax.swing.UIDefaults
AbstractMap
到这里集合就写得差不多了,肯定有漏的,也不是那么深入,但是一点点的进步也叫进步。有一句话叫: 不积跬步,无以至千里;不积小流,无以成江海。