深刻理解IdentityHashMap

新建POJO

package test;

public class Cat {
	private String name;
	private Integer age;

	public Cat(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof Cat)) {
			return false;
		}
		Cat p = (Cat) obj;
		if (this.name.equals(p.name) && this.age == p.age) {
			return true;
		} else {
			return false;
		}
	}
	public int hashCode() {
		return this.name.hashCode() * this.age;
	}

	public String toString() {
		return "姓名:" + this.name + ";年龄:" + this.age;
	}
}

测试:
public class TestMap  {
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void main(String[] args) {
		Map mp = new HashMap<String, String>();
		mp.put("1", "s");
		mp.put("2", "t");
		/*Collection ct = mp.values();
		System.out.println(ct.toString());*/
		mp.put("1", "t");
		Set<Map.Entry<String, String>> allSet = mp.entrySet();
		Iterator<Map.Entry<String, String>> iter = allSet.iterator();
		while (iter.hasNext()) {
			Map.Entry<String, String> me = iter.next();
			System.out.println(me.getKey() + " --> " + me.getValue());
		}
		//HashMap
		Map mpx = new HashMap<Cat, String>();
		mpx.put(new Cat("kitty",1), "kitty_1");
		mpx.put(new Cat("jime",2), "jime_2");
		mpx.put(new Cat("kitty",1), "kitty_2");
		Set<Map.Entry<Cat, String>> allSetx = mpx.entrySet();
		Iterator<Map.Entry<Cat, String>> iterx = allSetx.iterator();
		while (iterx.hasNext()) {
			Map.Entry<Cat, String> me = iterx.next();
			System.out.println(me.getKey() + " --> " + me.getValue());
		}
                System.out.println("==============IdentityHashMap:");
		//IdentityHashMap
		Map imp = new IdentityHashMap<Cat, String>();
		imp.put(new Cat("kitty",1), "kitty_1");
		imp.put(new Cat("jime",2), "jime_2");
		imp.put(new Cat("kitty",1), "kitty_2");
		Set<Map.Entry<Cat, String>> iSet = imp.entrySet();
		Iterator<Map.Entry<Cat, String>> iterxx = iSet.iterator();
		while (iterxx.hasNext()) {
			Map.Entry<Cat, String> me = iterxx.next();
			System.out.println(me.getKey() + " --> " + me.getValue());
		}
	}
}

控制台输出:
2 --> t
1 --> t
姓名:jime;年龄:2 --> jime_2
姓名:kitty;年龄:1 --> kitty_2
==============IdentityHashMap:
姓名:kitty;年龄:1 --> kitty_2
姓名:kitty;年龄:1 --> kitty_1
姓名:jime;年龄:2 --> jime_2
查看HashMap的Put(K,V)
public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
	    //比较的是哈希值,key
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

查看:IdentityHashMap.put(Object obj, Object obj1)
public Object put(Object obj, Object obj1)
    {
        Object obj2 = maskNull(obj);
        Object aobj[] = table;
        int i = aobj.length;
        int j;
        Object obj3;
        for(j = hash(obj2, i); (obj3 = aobj[j]) != null; j = nextKeyIndex(j, i))
	    //比较的两个对象
            if(obj3 == obj2)
            {
                Object obj4 = aobj[j + 1];
                aobj[j + 1] = obj1;
                return obj4;
            }

        modCount++;
        aobj[j] = obj2;
        aobj[j + 1] = obj1;
        if(++size >= threshold)
            resize(i);
        return null;
    }

总结:
1.简单说IdentityHashMap与常用的HashMap的区别是:
前者比较key时是“引用相等”而后者是“对象相等”,即对于k1和k2,当k1==k2时,
IdentityHashMap认为两个key相等,而HashMap只有在k1.equals(k2) == true 时才会认为两个key相等。
2.IdentityHashMap 允许使用null作为key和value. 不保证任何Key-value对的之间的顺序,
更不能保证他们的顺序随时间的推移不会发生变化。
3.IdentityHashMap有其特殊用途,比如序列化或者深度复制。或者记录对象代理。
举个例子,jvm中的所有对象都是独一无二的,哪怕两个对象是同一个class的对象
,而且两个对象的数据完全相同,对于jvm来说,他们也是完全不同的,
如果要用一个map来记录这样jvm中的对象,你就需要用IdentityHashMap,而不能使用其他Map实现

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

成为java高手的八大条件 - 2016-09-23 14:09:05

成为java高手的八大条件 世界上并没有成为高手的捷径,但一些基本原则是可以遵循的。兄弟连JavaEE培训导师,告诉你学习java有这样的素质才能成为高手! 1、扎实的基础 数据结构、离散数学、编译原理,这些是所有计算机科学的基础,如果不掌握它们,很难写出高水平的程序。程序人人都会写,但当你发现写到一定程度很难再提高的时候,就应该想想是不是要回过头来学学这些最基本的理论。不要一开始就去学OOP,即使你再精通OOP,遇到一些基本算法的时候可能也会束手无策。因此多读一些计算机基础理论方面的书籍是非常有必要的。

MySQL助理配置 - 2016-09-23 14:09:05

基本配置   你需要经常察看以下3个配置项。不然,可能很快就会出问题。 innodb_buffer_pool_size:这是你安装完InnoDB后第一个应该设置的选项。缓冲池是数据和索引缓存的地方:这个值越大越好,这能保证你在大多数的读取操作时使用的是内存而不是硬盘。典型的值是5-6GB(8GB内存),20-25GB(32GB内存),100-120GB(128GB内存)。 innodb_log_file_size:这是redo日志的大小。redo日志被用于确保写操作快速而可靠并且在崩溃时恢复。一直到MyS
9个基于Java的搜索引擎框架   1.Java全文搜索引擎框架Lucene   毫 无疑问,Lucene是目前最受欢迎的Java全文搜索框架,准确地说,它是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引 擎。Lucene为开发人员提供了相当完整的工具包,可以非常方便地实现强大的全文检索功能。下面有几款搜索引擎框架也是基于Lucene实现的。 官方网站: http://lucene.apache.org/   2.开源Java搜索引擎Nutch   Nutch 是一个开源Java实

Quartz定时任务的实现及详解 - 2016-09-23 04:09:09

Quartz定时任务的实现及详解 平常工作中经常遇到写定时任务的,这次做一次记录和解析分享给大家,共同学习进步,遇到写的不对的地方也请大家指教 用例:比如每天凌晨我们要让系统定时执行一些耗费服务器的事情,或者其他的一些定时任务 相关的jar包在附件,如有需要自行下载 1、 首先怎么启动这个Quartz呢? 在项目启动的时候,让web.xml读取我们的定时器配置文件,如下所示 param-namecontextConfigLocation/param-nameparam-value/WEB-INF/conf

JDBC连接数据库的步骤详解 - 2016-09-23 04:09:09

   Java Code  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 8
编译Qconf git clone https://github.com/Qihoo360/QConf.git cd Qconf //注意如果不是root永恒,可能需要使用sudo权限 mkdir build cd build // 默认安装在/usr/local/qconf目录,后面的命令指定安装目录 cmake ..  或者 cmake .. -DCMAKE_INSTALL_PREFIX=/install/prefix make make install //如果出错,也就下面几个错误了 sudo l

Java 使用默认浏览器打开 URL - 2016-09-22 19:09:07

      URI uri = new URI(url);Desktop desktop = Desktop.getDesktop();if (desktop.isSupported(Desktop.Action.BROWSE)) {desktop.browse(uri);}            

Java线程Dump分析工具--jstack - 2016-09-22 18:09:03

Java线程Dump分析工具--jstack jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:      jstack [-l][F] pid      如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另

java spring整合websocket - 2016-09-21 17:09:03

这几天项目中需要整合websocket来支持业务,从网上看了好多资料。但是都很杂乱,我尝试了好多回,走了很多弯路,跳了很多坑~~~~~~。通过两天的调试终于成功!!!现在把调试步骤和容易出现的问题都列出来,让和我这样的新手有点帮助。开始上代码......... 【 备注:spring的版本4.0+ ,tomcat :7.50 + , jdk:1.8 】 java Spring 整合 websocket 有两种方法 : 1:配置方法 [网上有很多] (地址: http://blog.csdn.net/sti

Java命令行classpath的设置 - 2016-09-21 17:09:03

在练习JavaDB Embedded模式的Java编程时候,直接用编辑器开发,所以需要用平时不怎么用的命令行来编译代码,按照普通的方式进行编译之后,开始运行,结果弹出错误提示。 java -classpath derby.jar JavaDBTest 错误: 找不到或无法加载主类 JavaDBTest 想不通是怎么回事。后来发现,需要将当前目录也加入到ClassPath中 java -classpath .;derby.jar JavaDBTest 这样才能成功运行 Load the EmbeddedDri