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;
}