Java教程

技术问答-11 java中的集合(6)-Map

本文主要是介绍技术问答-11 java中的集合(6)-Map,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Map

一、Map简介

Map提供了一个更通用的元素存储方法。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
推荐看一篇文章 很受用

  • ConcurrentHashMap支持并发操作也就是线程安全的
    整个ConcurrentHashMap 由一个个Segment组成,Segment代表“段”或“部分”的意思,很多地方都会将其描述为分段锁
  • 简单理解就是,ConcurrentHashMap是一个Segment数组,
  • Segment通过集成ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住一个Segment,这样只要保证每个Segment是线程安全的,也就实现了全局的线程安全。
  • 具体介绍以及jdk1.8对HashMap的升级 在上边推荐的文章中已经提到,去看那篇文章就行了 文章写得很好 ,但是这个很难理解 需要时间领悟。
三、Map 专用类

专用Map 通常我们不需要亲自创建这类map 而是通过某些其他类对其进行访问
java.util.jar.Attributes javax.print.attribute.standard.PrinterStateReasons
java.security.Provider java.awt.RenderingHints javax.swing.UIDefaults

四、一个帮助我们实现自己的Map类的抽象类

AbstractMap

到这里集合就写得差不多了,肯定有漏的,也不是那么深入,但是一点点的进步也叫进步。有一句话叫: 不积跬步,无以至千里;不积小流,无以成江海。

这篇关于技术问答-11 java中的集合(6)-Map的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!