IdentityHashMap

java.util.IdentityHashMap类利用哈希表实现 Map 接口,比较键(和值)时使用引用相等性代替对象相等性。 换句话说,在 IdentityHashMap 中,当且仅当 (k1==k2) 时,

才认为两个键 k1 和 k2 相等(在正常 Map 实现(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2)))。

此类不是 通用 Map实现!此类实现Map接口时,它有意违反Map的常规协定比较对象时强制使用equals方法。此类设计仅用于其中需要引用相等性语义的罕见情况。

 

此类的典型用法是拓扑保留对象图形转换,如序列化或深层复制。 要执行这样的转换,程序必须维护用于跟踪所有已处理对象引用的“节点表”。

节点表一定不等于不同对象,即使它们偶然相等也如此。

 

此类的另一种典型用法是维护代理对象。例如,调试设施可能希望为正在调试程序中的每个对象维护代理对象。

此类提供所有的可选映射操作,并且允许 null 值和 null 键。此类对映射的顺序不提供任何保证;特别是不保证顺序随时间的推移保持不变。

此类提供基本操作(get 和 put)的稳定性能,假定系统标识了将桶间元素正确分开的哈希函数 (System.identityHashCode(Object))。

此类具有一个调整参数(影响性能但不影响语义):expected maximum size。此参数是希望映射保持的键值映射关系最大数。在内部,此参数用于确定最初组成哈希表的桶数。

未指定所期望的最大数量和桶数之间的确切关系。默认的价值加载因子为2/3,在重新哈希后,加载因子变为1/3.当哈希表中的条目数超出了加载因子与当前容量的乘积时,

通过调用 reszie 方法将容量翻倍,重新进行哈希。增加桶数,重新哈希,可能相当昂贵。因此创建具有足够大的期望最大数量的标识哈希映射更合算。

 

另一方面,对 collection 视图进行迭代所需的时间与哈希表中的桶数成正比, 所以如果特别注重迭代性能或内存使用,则不宜将期望的最大数量设置得过高。

注意,此实现不是同步的。如果多个线程同时访问此映射,并且其中至少一个线程从结构上修改了该映射, 

则其必须保持外部同步(结构上的修改是指添加或删除一个或多个映射关系的操作;仅改变与实例已经包含的键关联的值不是结构上的修改)。

一般通过对封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedMap方法来“包装”该映射。

 最好在创建时完成这一操作,以防止对映射进行意外的不同步访问,如下所示:

Map m = Collections.synchronizedMap(new HashMap(...));

 

由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的:在迭代器创建之后, 如果从结构上对映射进行修改,除非通过迭代器自身的 remove 或 add 方法,

其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。 因此面对并发的修改,迭代器很快就会失败,而不会在将来不确定的时间任意发生不确定行为的风险。

 

注意,此类迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何强有力的保证。

因此,编写依赖于此异常的程序的方式是错误的,正确做法是: 迭代器的快速失败行为应该仅用于检测程序错误。 

实现注意事项:此为简单的线性探头哈希表,如Sedgewick 和 Knuth 原文示例中所述。 该数组交替保持键和值(对于大型表来说,它比使用独立组保持键和值更具优势)。

对于多数 JRE 实现和混合操作, 此类比 HashMap(它使用链 而不使用线性探头)能产生更好的性能。 

 

 注意1:允许 null 值和 null 键。

 注意2:此类对映射的顺序不提供任何保证;特别是不保证顺序随时间的推移保持不变。

 注意3:此实现不是同步的。

 注意4:迭代器的快速失败行为不能得到保证。

 注意5:此为简单的线性探头哈希表。对于多数 JRE 实现和混合操作, 此类比HashMap(它使用链而不使用线性探头)能产生更好的性能。 

 

构造函数
Public Constructors
  IdentityHashMap()
Creates an IdentityHashMap with default expected maximum size.
  IdentityHashMap(int maxSize)
Creates an IdentityHashMap with the specified maximum size parameter.
  IdentityHashMap(Map<? extends K, ? extends V> map)
Creates an IdentityHashMap using the given map as initial values.
 
实例1
package test;
import java.util.IdentityHashMap;  
import java.util.Iterator;  
import java.util.Map;  
import java.util.Set;  
class Person {                              // 定义Person类  
    private String name;                    // 定义name属性  
    private int age;                        // 定义age属性  
    public Person(String name, int age) {   // 通过构造方法为属性赋值  
        this.name = name;                   // 为name属性赋值  
        this.age = age;                     // 为age属性赋值  
    }  
    public boolean equals(Object obj) {     // 覆写equals()方法  
        if (this == obj) {                  // 判断地址是否相等  
            return true;                    // 返回true表示同一对象  
        }  
        if (!(obj instanceof Person)) {     // 传递进来的不是本类的对象  
            return false;                   // 返回false表示不是同一对象  
        }  
        Person p = (Person) obj;            // 进行向下转型  
        if (this.name.equals(p.name) && this.age == p.age) {  
            return true ;                   // 属性依次比较,相等返回true  
        }else{  
            return false ;                  // 属性内容不相等,返回false  
        }  
    }  
    public int hashCode(){                    // 覆写hashCode()方法  
        return this.name.hashCode() * this.age ;  // 计算公式  
    }  
    public String toString() {                    // 覆写toString()方法  
        return "姓名:" + this.name + ";年龄:" + this.age;   // 返回信息  
    }  
}   

public class IdentityHashMapDemo {
    public static void main(String[] args) {
        Map<Person, String> map = null;// 声明Map对象,指定泛型类型
        map = new IdentityHashMap<Person, String>();//实例化Map对象
        map.put(new Person("张三", 30), "zhangsan_1");//增加内容
        map.put(new Person("张三", 30), "zhangsan_2");//增加内容,key重复  
        map.put(new Person("李四", 31), "lisi");//增加内容  
        Set<Map.Entry<Person, String>> allSet = null;//声明一个Set集合  
        allSet = map.entrySet();// 将Map接口实例变为Set接口实例  
        Iterator<Map.Entry<Person, String>> iter = null;// 声明Iterator对象  
        iter = allSet.iterator(); //实例化Iterator对象  
        while (iter.hasNext()) {// 迭代输出  
            Map.Entry<Person, String> me = iter.next();// 每个对象都是Map.Entry实例  
            System.out.println(me.getKey()+ " --> " + me.getValue());// 输出key和value  
        }
    }  
} 
输出如下:
姓名:李四;年龄:31 --> lisi 姓名:张三;年龄:30 --> zhangsan_1 姓名:张三;年龄:30 --> zhangsan_2
参看 http://docs.oracle.com/javase/7/docs/api/java/util/IdentityHashMap.html
posted @ 2014-10-09 21:50  princessd8251  阅读(233)  评论(0)    收藏  举报