集合框架map学习笔记一IdentityHashMap

时间:2023-02-26 11:03:52

Map: 

1、HashMap 

2、LinkedHashMap 

3、IdentityHashMap 

4、WeakHashMap 

5、TreeMap 

6、EnumMap 

7、ConcurrentHashMap 

8、ConcurrentSkipListMap 

今天主要学习的是IdentityHashMap


1、IdentityHashMap

IdentityHashMap判断两个键值k1和 k2相等的条件是 k1 == k2 。在正常的Map 实现(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2))。IdentityHashMap类利用哈希表实现 Map 接口,比较键(和值)时使用引用相等性代替对象相等性。该类不是 通用 Map 实现!此类实现 Map 接口时,它有意违反 Map 的常规协定,该协定在比较对象时强制使用 equals 方法。此类设计仅用于其中需要引用相等性语义的罕见情况。


2、IdentityHashMap的特殊用法

IdentityHashMap主要是用于key值的重复使用。因为常规的map中,key值的比较条件为:(k1==null ? k2==null : e1.equals(e2));而IdentityHashMap必须是k1==k2;

实验:

public class TestIdentityHashMap {

/**
* @param args
*/
public static void main(String[] args) {
//if hashmap,the key 只能是一种球
HashMap<Ball, String> hm = new HashMap<Ball, String>();
hm.put(new Ball(1,"red"), "A");
hm.put(new Ball(1,"red"), "B");
hm.put(new Ball(1,"red"), "C");
hm.put(new Ball(2,"yellow"), "D");

Iterator<Entry<Ball,String>> iter = hm.entrySet().iterator();
System.out.println("in HashMap ---------------------------");
while(iter.hasNext()){
Entry<Ball,String> ball = iter.next();
System.out.println(ball.getKey()+" , "+ball.getValue());
}

//if IdentityHashMap,the key 可以是一种球里面的很多个
IdentityHashMap<Ball, String> ihm = new IdentityHashMap<Ball, String>();
ihm.put(new Ball(1,"red"), "A");
ihm.put(new Ball(1,"red"), "B");
ihm.put(new Ball(1,"red"), "C");
ihm.put(new Ball(2,"yellow"), "D");

Iterator<Entry<Ball,String>> iter1 = ihm.entrySet().iterator();
System.out.println("in IdentityHashMap ---------------------------");
while(iter1.hasNext()){
Entry<Ball,String> ball = iter1.next();
System.out.println(ball.getKey()+" , "+ball.getValue());
}
}


}
class Ball{

int diameter;

String color;

public Ball(int diameter , String color){
this.diameter = diameter;
this.color = color;
}

@Override
public boolean equals(Object o){
if(o instanceof Ball){
Ball ball = (Ball)o;
if((ball.color.equalsIgnoreCase(color))&&(ball.diameter==diameter)){
return true;
}
}
return false;
}

@Override
public int hashCode(){
return this.color.hashCode() * this.diameter ;
}

@Override
public String toString(){
return "(diameter:"+diameter+",color:"+color+")";

}
}

输出的结果为:

in HashMap ---------------------------
(diameter:1,color:red) , C
(diameter:2,color:yellow) , D
in IdentityHashMap ---------------------------
(diameter:1,color:red) , B
(diameter:1,color:red) , A
(diameter:1,color:red) , C
(diameter:2,color:yellow) , D

3、IdentityHashMap的数据存放

IdentityHashMap的put方法中将元素<key,value>不再是放入entry[]的桶中,而是一个Object[]对象,将key占用一个index下标,然后value也占用一个,如果当IdentityHashMap的容量达到3分之2的时候,就会进行动态扩充一倍的容量。

IdentityHashMap和HashMap在动态扩充容量上原理相同,只是IdentityHashMap的加载因子是一定的,而HashMap是可以自己定义的。

 public V put(K key, V value) {
Object k = maskNull(key);
Object[] tab = table;
int len = tab.length;
int i = hash(k, len);

Object item;
while ( (item = tab[i]) != null) {
if (item == k) {
V oldValue = (V) tab[i + 1];
tab[i + 1] = value;
return oldValue;
}
i = nextKeyIndex(i, len);
}

modCount++;
tab[i] = k;
tab[i + 1] = value;
if (++size >= threshold)
resize(len); // len == 2 * current capacity.
return null;
}