/** Converts the flat map data to a map. */ private void convertToMap() { delegateMap = createDelegateMap(); switch (size) { // drop through case 3: delegateMap.put(key3, value3); case 2: delegateMap.put(key2, value2); case 1: delegateMap.put(key1, value1); } size = 0; hash1 = hash2 = hash3 = 0; key1 = key2 = key3 = null; value1 = value2 = value3 = null; }
/** * Checks whether the map contains the specified key. * * @param key the key to search for * @return true if the map contains the key */ public boolean containsKey(Object key) { if (delegateMap != null) { return delegateMap.containsKey(key); } if (key == null) { switch (size) { // drop through case 3: if (key3 == null) return true; case 2: if (key2 == null) return true; case 1: if (key1 == null) return true; } } else { if (size > 0) { int hashCode = key.hashCode(); switch (size) { // drop through case 3: if (hash3 == hashCode && key.equals(key3)) return true; case 2: if (hash2 == hashCode && key.equals(key2)) return true; case 1: if (hash1 == hashCode && key.equals(key1)) return true; } } } return false; }
/** * Checks whether the map contains the specified value. * * @param value the value to search for * @return true if the map contains the key */ public boolean containsValue(Object value) { if (delegateMap != null) { return delegateMap.containsValue(value); } if (value == null) { // drop through switch (size) { case 3: if (value3 == null) return true; case 2: if (value2 == null) return true; case 1: if (value1 == null) return true; } } else { switch (size) { // drop through case 3: if (value.equals(value3)) return true; case 2: if (value.equals(value2)) return true; case 1: if (value.equals(value1)) return true; } } return false; }
/** * Gets the value mapped to the key specified. * * @param key the key * @return the mapped value, null if no match */ public Object get(Object key) { if (delegateMap != null) { return delegateMap.get(key); } if (key == null) { switch (size) { // drop through case 3: if (key3 == null) return value3; case 2: if (key2 == null) return value2; case 1: if (key1 == null) return value1; } } else { if (size > 0) { int hashCode = key.hashCode(); switch (size) { // drop through case 3: if (hash3 == hashCode && key.equals(key3)) return value3; case 2: if (hash2 == hashCode && key.equals(key2)) return value2; case 1: if (hash1 == hashCode && key.equals(key1)) return value1; } } } return null; }
/** * Gets the map as a String. * * @return a string version of the map */ public String toString() { if (delegateMap != null) { return delegateMap.toString(); } if (size == 0) { return "{}"; } StringBuffer buf = new StringBuffer(128); buf.append('{'); switch (size) { // drop through case 3: buf.append((key3 == this ? "(this Map)" : key3)); buf.append('='); buf.append((value3 == this ? "(this Map)" : value3)); buf.append(','); case 2: buf.append((key2 == this ? "(this Map)" : key2)); buf.append('='); buf.append((value2 == this ? "(this Map)" : value2)); buf.append(','); case 1: buf.append((key1 == this ? "(this Map)" : key1)); buf.append('='); buf.append((value1 == this ? "(this Map)" : value1)); } buf.append('}'); return buf.toString(); }
/** * Gets an iterator over the map. Changes made to the iterator affect this map. * * <p>A MapIterator returns the keys in the map. It also provides convenient methods to get the * key and value, and set the value. It avoids the need to create an entrySet/keySet/values * object. It also avoids creating the Map Entry object. * * @return the map iterator */ public MapIterator mapIterator() { if (delegateMap != null) { return delegateMap.mapIterator(); } if (size == 0) { return EmptyMapIterator.INSTANCE; } return new FlatMapIterator(this); }
/** * Puts all the values from the specified map into this map. * * @param map the map to add * @throws NullPointerException if the map is null */ public void putAll(Map map) { int size = map.size(); if (size == 0) { return; } if (delegateMap != null) { delegateMap.putAll(map); return; } if (size < 4) { for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); put(entry.getKey(), entry.getValue()); } } else { convertToMap(); delegateMap.putAll(map); } }
/** * Clears the map, resetting the size to zero and nullifying references to avoid garbage * collection issues. */ public void clear() { if (delegateMap != null) { delegateMap.clear(); // should aid gc delegateMap = null; // switch back to flat mode } else { size = 0; hash1 = hash2 = hash3 = 0; key1 = key2 = key3 = null; value1 = value2 = value3 = null; } }
/** * Gets the standard Map hashCode. * * @return the hash code defined in the Map interface */ public int hashCode() { if (delegateMap != null) { return delegateMap.hashCode(); } int total = 0; switch (size) { // drop through case 3: total += (hash3 ^ (value3 == null ? 0 : value3.hashCode())); case 2: total += (hash2 ^ (value2 == null ? 0 : value2.hashCode())); case 1: total += (hash1 ^ (value1 == null ? 0 : value1.hashCode())); } return total; }
/** * Compares this map with another. * * @param obj the object to compare to * @return true if equal */ public boolean equals(Object obj) { if (obj == this) { return true; } if (delegateMap != null) { return delegateMap.equals(obj); } if (obj instanceof Map == false) { return false; } Map other = (Map) obj; if (size != other.size()) { return false; } if (size > 0) { Object otherValue = null; switch (size) { // drop through case 3: if (other.containsKey(key3) == false) { return false; } otherValue = other.get(key3); if (value3 == null ? otherValue != null : !value3.equals(otherValue)) { return false; } case 2: if (other.containsKey(key2) == false) { return false; } otherValue = other.get(key2); if (value2 == null ? otherValue != null : !value2.equals(otherValue)) { return false; } case 1: if (other.containsKey(key1) == false) { return false; } otherValue = other.get(key1); if (value1 == null ? otherValue != null : !value1.equals(otherValue)) { return false; } } } return true; }
/** * Gets the values view of the map. Changes made to the view affect this map. To simply iterate * through the values, use {@link #mapIterator()}. * * @return the values view */ public Collection values() { if (delegateMap != null) { return delegateMap.values(); } return new Values(this); }
/** * Gets the keySet view of the map. Changes made to the view affect this map. To simply iterate * through the keys, use {@link #mapIterator()}. * * @return the keySet view */ public Set keySet() { if (delegateMap != null) { return delegateMap.keySet(); } return new KeySet(this); }
/** * Gets the entrySet view of the map. Changes made to the view affect this map. The Map Entry is * not an independent object and changes as the iterator progresses. To simply iterate through the * entries, use {@link #mapIterator()}. * * @return the entrySet view */ public Set entrySet() { if (delegateMap != null) { return delegateMap.entrySet(); } return new EntrySet(this); }
/** * Removes the specified mapping from this map. * * @param key the mapping to remove * @return the value mapped to the removed key, null if key not in map */ public Object remove(Object key) { if (delegateMap != null) { return delegateMap.remove(key); } if (size == 0) { return null; } if (key == null) { switch (size) { // drop through case 3: if (key3 == null) { Object old = value3; hash3 = 0; key3 = null; value3 = null; size = 2; return old; } if (key2 == null) { Object old = value3; hash2 = hash3; key2 = key3; value2 = value3; hash3 = 0; key3 = null; value3 = null; size = 2; return old; } if (key1 == null) { Object old = value3; hash1 = hash3; key1 = key3; value1 = value3; hash3 = 0; key3 = null; value3 = null; size = 2; return old; } return null; case 2: if (key2 == null) { Object old = value2; hash2 = 0; key2 = null; value2 = null; size = 1; return old; } if (key1 == null) { Object old = value2; hash1 = hash2; key1 = key2; value1 = value2; hash2 = 0; key2 = null; value2 = null; size = 1; return old; } return null; case 1: if (key1 == null) { Object old = value1; hash1 = 0; key1 = null; value1 = null; size = 0; return old; } } } else { if (size > 0) { int hashCode = key.hashCode(); switch (size) { // drop through case 3: if (hash3 == hashCode && key.equals(key3)) { Object old = value3; hash3 = 0; key3 = null; value3 = null; size = 2; return old; } if (hash2 == hashCode && key.equals(key2)) { Object old = value3; hash2 = hash3; key2 = key3; value2 = value3; hash3 = 0; key3 = null; value3 = null; size = 2; return old; } if (hash1 == hashCode && key.equals(key1)) { Object old = value3; hash1 = hash3; key1 = key3; value1 = value3; hash3 = 0; key3 = null; value3 = null; size = 2; return old; } return null; case 2: if (hash2 == hashCode && key.equals(key2)) { Object old = value2; hash2 = 0; key2 = null; value2 = null; size = 1; return old; } if (hash1 == hashCode && key.equals(key1)) { Object old = value2; hash1 = hash2; key1 = key2; value1 = value2; hash2 = 0; key2 = null; value2 = null; size = 1; return old; } return null; case 1: if (hash1 == hashCode && key.equals(key1)) { Object old = value1; hash1 = 0; key1 = null; value1 = null; size = 0; return old; } } } } return null; }
/** * Puts a key-value mapping into this map. * * @param key the key to add * @param value the value to add * @return the value previously mapped to this key, null if none */ public Object put(Object key, Object value) { if (delegateMap != null) { return delegateMap.put(key, value); } // change existing mapping if (key == null) { switch (size) { // drop through case 3: if (key3 == null) { Object old = value3; value3 = value; return old; } case 2: if (key2 == null) { Object old = value2; value2 = value; return old; } case 1: if (key1 == null) { Object old = value1; value1 = value; return old; } } } else { if (size > 0) { int hashCode = key.hashCode(); switch (size) { // drop through case 3: if (hash3 == hashCode && key.equals(key3)) { Object old = value3; value3 = value; return old; } case 2: if (hash2 == hashCode && key.equals(key2)) { Object old = value2; value2 = value; return old; } case 1: if (hash1 == hashCode && key.equals(key1)) { Object old = value1; value1 = value; return old; } } } } // add new mapping switch (size) { default: convertToMap(); delegateMap.put(key, value); return null; case 2: hash3 = (key == null ? 0 : key.hashCode()); key3 = key; value3 = value; break; case 1: hash2 = (key == null ? 0 : key.hashCode()); key2 = key; value2 = value; break; case 0: hash1 = (key == null ? 0 : key.hashCode()); key1 = key; value1 = value; break; } size++; return null; }
/** * Gets the size of the map. * * @return the size */ public int size() { if (delegateMap != null) { return delegateMap.size(); } return size; }