001: /*
002: * Copyright 2003-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections.map;
017:
018: import java.io.IOException;
019: import java.io.ObjectInputStream;
020: import java.io.ObjectOutputStream;
021: import java.io.Serializable;
022: import java.util.Map;
023:
024: /**
025: * A <code>Map</code> implementation that matches keys and values based
026: * on <code>==</code> not <code>equals()</code>.
027: * <p>
028: * This map will violate the detail of various Map and map view contracts.
029: * As a general rule, don't compare this map to other maps.
030: * <p>
031: * <strong>Note that IdentityMap is not synchronized and is not thread-safe.</strong>
032: * If you wish to use this map from multiple threads concurrently, you must use
033: * appropriate synchronization. The simplest approach is to wrap this map
034: * using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw
035: * exceptions when accessed by concurrent threads without synchronization.
036: *
037: * @since Commons Collections 3.0
038: * @version $Revision: 348007 $ $Date: 2005-11-21 22:52:57 +0000 (Mon, 21 Nov 2005) $
039: *
040: * @author java util HashMap
041: * @author Stephen Colebourne
042: */
043: public class IdentityMap extends AbstractHashedMap implements
044: Serializable, Cloneable {
045:
046: /** Serialisation version */
047: private static final long serialVersionUID = 2028493495224302329L;
048:
049: /**
050: * Constructs a new empty map with default size and load factor.
051: */
052: public IdentityMap() {
053: super (DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
054: }
055:
056: /**
057: * Constructs a new, empty map with the specified initial capacity.
058: *
059: * @param initialCapacity the initial capacity
060: * @throws IllegalArgumentException if the initial capacity is less than one
061: */
062: public IdentityMap(int initialCapacity) {
063: super (initialCapacity);
064: }
065:
066: /**
067: * Constructs a new, empty map with the specified initial capacity and
068: * load factor.
069: *
070: * @param initialCapacity the initial capacity
071: * @param loadFactor the load factor
072: * @throws IllegalArgumentException if the initial capacity is less than one
073: * @throws IllegalArgumentException if the load factor is less than zero
074: */
075: public IdentityMap(int initialCapacity, float loadFactor) {
076: super (initialCapacity, loadFactor);
077: }
078:
079: /**
080: * Constructor copying elements from another map.
081: *
082: * @param map the map to copy
083: * @throws NullPointerException if the map is null
084: */
085: public IdentityMap(Map map) {
086: super (map);
087: }
088:
089: //-----------------------------------------------------------------------
090: /**
091: * Gets the hash code for the key specified.
092: * This implementation uses the identity hash code.
093: *
094: * @param key the key to get a hash code for
095: * @return the hash code
096: */
097: protected int hash(Object key) {
098: return System.identityHashCode(key);
099: }
100:
101: /**
102: * Compares two keys for equals.
103: * This implementation uses <code>==</code>.
104: *
105: * @param key1 the first key to compare
106: * @param key2 the second key to compare
107: * @return true if equal by identity
108: */
109: protected boolean isEqualKey(Object key1, Object key2) {
110: return (key1 == key2);
111: }
112:
113: /**
114: * Compares two values for equals.
115: * This implementation uses <code>==</code>.
116: *
117: * @param value1 the first value to compare
118: * @param value2 the second value to compare
119: * @return true if equal by identity
120: */
121: protected boolean isEqualValue(Object value1, Object value2) {
122: return (value1 == value2);
123: }
124:
125: /**
126: * Creates an entry to store the data.
127: * This implementation creates an IdentityEntry instance.
128: *
129: * @param next the next entry in sequence
130: * @param hashCode the hash code to use
131: * @param key the key to store
132: * @param value the value to store
133: * @return the newly created entry
134: */
135: protected HashEntry createEntry(HashEntry next, int hashCode,
136: Object key, Object value) {
137: return new IdentityEntry(next, hashCode, key, value);
138: }
139:
140: //-----------------------------------------------------------------------
141: /**
142: * HashEntry
143: */
144: protected static class IdentityEntry extends HashEntry {
145:
146: protected IdentityEntry(HashEntry next, int hashCode,
147: Object key, Object value) {
148: super (next, hashCode, key, value);
149: }
150:
151: public boolean equals(Object obj) {
152: if (obj == this ) {
153: return true;
154: }
155: if (obj instanceof Map.Entry == false) {
156: return false;
157: }
158: Map.Entry other = (Map.Entry) obj;
159: return (getKey() == other.getKey())
160: && (getValue() == other.getValue());
161: }
162:
163: public int hashCode() {
164: return System.identityHashCode(getKey())
165: ^ System.identityHashCode(getValue());
166: }
167: }
168:
169: //-----------------------------------------------------------------------
170: /**
171: * Clones the map without cloning the keys or values.
172: *
173: * @return a shallow clone
174: */
175: public Object clone() {
176: return super .clone();
177: }
178:
179: /**
180: * Write the map out using a custom routine.
181: */
182: private void writeObject(ObjectOutputStream out) throws IOException {
183: out.defaultWriteObject();
184: doWriteObject(out);
185: }
186:
187: /**
188: * Read the map in using a custom routine.
189: */
190: private void readObject(ObjectInputStream in) throws IOException,
191: ClassNotFoundException {
192: in.defaultReadObject();
193: doReadObject(in);
194: }
195:
196: }
|