网络知识 娱乐 你没用过这个集合吧?IdentityHashMap

你没用过这个集合吧?IdentityHashMap

模仿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
{
...
}

Cloneable是个啥?https://blog.fondme.cn/apidoc/jdk-1.8-google/java/lang/Cloneable.html

构造方法摘要

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方法。 该类仅在需要引用相等语义的罕见情况下才能使用。

我自己使用的特点是啥呢?

  1. 是个map集合
  2. K,V都允许为null
  3. K允许重复且不覆盖
  4. 构造方法参数适合

方法摘要

clone

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