模仿HashMap写一篇IdentityHashMap的整理。
API截图:
https://blog.fondme.cn/apidoc/jdk-1.8-google/java/util/IdentityHashMap.html
public class IdentityHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, java.io.Serializable, Cloneable
{
...
}
Constructor and Description |
---|
IdentityHashMap()构造一个带有默认预期最大大小的新的空标识哈希映射(21)。 |
IdentityHashMap(int expectedMaxSize)构造一个具有指定的预期最大大小的新的空白地图。 |
IdentityHashMap(Map<? extends K,? extends V> m)构造一个新的标识哈希映射,其中包含指定地图中的键值映射。 |
1. public IdentityHashMap() {
init(DEFAULT_CAPACITY);
}
2. public IdentityHashMap(int expectedMaxSize) {
if (expectedMaxSize < 0)
throw new IllegalArgumentException("expectedMaxSize is negative: "
+ expectedMaxSize);
init(capacity(expectedMaxSize));
}
3. public IdentityHashMap(Map<? extends K, ? extends V> m) {
// Allow for a bit of growth
this((int) ((1 + m.size()) * 1.1));
putAll(m);
}
这个类不是通用的Map实现! 虽然这个类实现了Map接口,但是它有意违反了Map's通用合同,当对比比较时,它要求使用equals方法。 该类仅在需要引用相等语义的罕见情况下才能使用。
我自己使用的特点是啥呢?
方法摘要
public Object clone()
返回此标识哈希映射的浅拷贝:键和值本身不被克隆。
clone
在类别 AbstractMap<K,V>
Cloneable
/**
* The initial capacity used by the no-args constructor.
* MUST be a power of two. The value 32 corresponds to the
* (specified) expected maximum size of 21, given a load factor
* of 2/3.
*/
哎嗨?初始容量大小32
private static final int DEFAULT_CAPACITY = 32;
/**
* The minimum capacity, used if a lower value is implicitly specified
* by either of the constructors with arguments. The value 4 corresponds
* to an expected maximum size of 2, given a load factor of 2/3.
* MUST be a power of two.
*/
private static final int MINIMUM_CAPACITY = 4;
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<29.
*
* In fact, the map can hold no more than MAXIMUM_CAPACITY-1 items
* because it has to have at least one slot with the key == null
* in order to avoid infinite loops in get(), put(), remove()
*/
最大容量1<<29
private static final int MAXIMUM_CAPACITY = 1 << 29;
Hashmap//最大的容量上限为 2^30
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* The table, resized as necessary. Length MUST always be a power of two.
*/
transient Object[] table; // non-private to simplify nested class access
/**
* The number of key-value mappings contained in this identity hash map.
*
* @serial
*/
int size;
put方法非线程安全的,仅判断了循环结束条件
public V put(K key, V value) {
final Object k = maskNull(key);
retryAfterResize: for (;;) {
final Object[] tab = table;
final int len = tab.length;
int i = hash(k, len);
for (Object item; (item = tab[i]) != null;
i = nextKeyIndex(i, len)) {
if (item == k) {
@SuppressWarnings("unchecked")
V oldValue = (V) tab[i + 1];
tab[i + 1] = value;
return oldValue;
}
}
final int s = size + 1;
// Use optimized form of 3 * s.
// Next capacity is len, 2 * current capacity.
if (s + (s << 1) > len && resize(len))
continue retryAfterResize;
modCount++;
tab[i] = k;
tab[i + 1] = value;
size = s;
return null;
}
}
如何变成线程安全的?
Map m = Collections.synchronizedMap(new IdentityHashMap(...));
把普通的集合转为线程安全的
Collections.synchronizedList()方法,都被同步
我是咋用的?
IdentityHashMap<String, String> subnetequipmentMap = new IdentityHashMap<>();
IdentityHashMap<String, String> subnetSrouterMap = new IdentityHashMap<>();
IdentityHashMap<String, String> subnetserverMap = new IdentityHashMap<>();
IdentityHashMap<String, String> routerFirewallMap = new IdentityHashMap<>();
IdentityHashMap<String, String> routerWsubnetMap = new IdentityHashMap<>();
IdentityHashMap<String, String> dyrouterSubnetMap = new IdentityHashMap<>();
for (Object o : mxCelArr) {
JSONObject object = JSON.parseObject(o.toString());
//校验拓扑连线,对象的属性判断
String edge = object.getString("edge");
//线的数组
//线edge
if (edge != null) {
//断头线
String source = object.getString("source");
String target = object.getString("target");
if (source == null || target == null) {
//回环线
} else if (source != null && target != null) {
if (!source.equals(target)) {
if (subnetIdList.contains(source) && serverIdList.contains(target) || subnetIdList.contains(target) && serverIdList.contains(source)) {
subnetserverMap.put(source, target);
}
if (srouterIdList.contains(source) && firewallIdList.contains(target) || srouterIdList.contains(target) && firewallIdList.contains(source)) {
routerFirewallMap.put(source, target);
}
if (subnetIdList.contains(source) && srouterIdList.contains(target) || subnetIdList.contains(target) && srouterIdList.contains(source)) {
subnetSrouterMap.put(source, target);
}
if (srouterIdList.contains(source) && wsubnetIdList.contains(target) || srouterIdList.contains(target) && wsubnetIdList.contains(source)) {
routerWsubnetMap.put(source, target);
}
if (equipmentIdList.contains(source) && subnetIdList.contains(target) || equipmentIdList.contains(target) && subnetIdList.contains(source)) {
subnetequipmentMap.put(source, target);
}
if (routerIdList.contains(source) && subnetIdList.contains(target) || routerIdList.contains(target) && subnetIdList.contains(source)) {
dyrouterSubnetMap.put(source, target);
}
}
}
}
}
map.put("subnetequipmentMap", subnetequipmentMap);
map.put("subnetSrouterMap", subnetSrouterMap);
map.put("subnetserverMap", subnetserverMap);
map.put("routerFirewallMap", routerFirewallMap);
map.put("routerWsubnetMap", routerWsubnetMap);
map.put("dyrouterSubnetMap", dyrouterSubnetMap);
return map;
}