📄 flat3map.java
字号:
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections.map;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.collections.IterableMap;
import org.apache.commons.collections.MapIterator;
import org.apache.commons.collections.ResettableIterator;
import org.apache.commons.collections.iterators.EmptyIterator;
import org.apache.commons.collections.iterators.EmptyMapIterator;
/**
* A <code>Map</code> implementation that stores data in simple fields until
* the size is greater than 3.
* <p>
* This map is designed for performance and can outstrip HashMap.
* It also has good garbage collection characteristics.
* <ul>
* <li>Optimised for operation at size 3 or less.
* <li>Still works well once size 3 exceeded.
* <li>Gets at size 3 or less are about 0-10% faster than HashMap,
* <li>Puts at size 3 or less are over 4 times faster than HashMap.
* <li>Performance 5% slower than HashMap once size 3 exceeded once.
* </ul>
* The design uses two distinct modes of operation - flat and delegate.
* While the map is size 3 or less, operations map straight onto fields using
* switch statements. Once size 4 is reached, the map switches to delegate mode
* and only switches back when cleared. In delegate mode, all operations are
* forwarded straight to a HashMap resulting in the 5% performance loss.
* <p>
* The performance gains on puts are due to not needing to create a Map Entry
* object. This is a large saving not only in performance but in garbage collection.
* <p>
* Whilst in flat mode this map is also easy for the garbage collector to dispatch.
* This is because it contains no complex objects or arrays which slow the progress.
* <p>
* Do not use <code>Flat3Map</code> if the size is likely to grow beyond 3.
* <p>
* <strong>Note that Flat3Map is not synchronized and is not thread-safe.</strong>
* If you wish to use this map from multiple threads concurrently, you must use
* appropriate synchronization. The simplest approach is to wrap this map
* using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw
* exceptions when accessed by concurrent threads without synchronization.
*
* @since Commons Collections 3.0
* @version $Revision: 348007 $ $Date: 2005-11-21 22:52:57 +0000 (Mon, 21 Nov 2005) $
*
* @author Stephen Colebourne
*/
public class Flat3Map implements IterableMap, Serializable, Cloneable {
/** Serialization version */
private static final long serialVersionUID = -6701087419741928296L;
/** The size of the map, used while in flat mode */
private transient int size;
/** Hash, used while in flat mode */
private transient int hash1;
/** Hash, used while in flat mode */
private transient int hash2;
/** Hash, used while in flat mode */
private transient int hash3;
/** Key, used while in flat mode */
private transient Object key1;
/** Key, used while in flat mode */
private transient Object key2;
/** Key, used while in flat mode */
private transient Object key3;
/** Value, used while in flat mode */
private transient Object value1;
/** Value, used while in flat mode */
private transient Object value2;
/** Value, used while in flat mode */
private transient Object value3;
/** Map, used while in delegate mode */
private transient AbstractHashedMap delegateMap;
/**
* Constructor.
*/
public Flat3Map() {
super();
}
/**
* Constructor copying elements from another map.
*
* @param map the map to copy
* @throws NullPointerException if the map is null
*/
public Flat3Map(Map map) {
super();
putAll(map);
}
//-----------------------------------------------------------------------
/**
* 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 size of the map.
*
* @return the size
*/
public int size() {
if (delegateMap != null) {
return delegateMap.size();
}
return size;
}
/**
* Checks whether the map is currently empty.
*
* @return true if the map is currently size zero
*/
public boolean isEmpty() {
return (size() == 0);
}
//-----------------------------------------------------------------------
/**
* 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;
}
//-----------------------------------------------------------------------
/**
* 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;
}
/**
* 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);
}
}
/**
* 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -