KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > runtime > ObjectMap


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.runtime;
12
13 import java.util.*;
14 import org.eclipse.core.internal.preferences.StringPool;
15
16 /**
17  * A specialized map implementation that is optimized for a small set of object
18  * keys.
19  *
20  * Implemented as a single array that alternates keys and values.
21  *
22  * Note: This class is copied from org.eclipse.core.resources
23  */

24 public class ObjectMap implements Map {
25     // 8 attribute keys, 8 attribute values
26
protected static final int DEFAULT_SIZE = 16;
27     protected static final int GROW_SIZE = 10;
28     protected int count = 0;
29     protected Object JavaDoc[] elements = null;
30     
31     /**
32      * Creates a new object map.
33      */

34     public ObjectMap() {
35         this(DEFAULT_SIZE);
36     }
37
38     /**
39      * Creates a new object map.
40      *
41      * @param initialCapacity
42      * The initial number of elements that will fit in the map.
43      */

44     public ObjectMap(int initialCapacity) {
45         elements = new Object JavaDoc[Math.max(initialCapacity * 2, 0)];
46     }
47
48     /**
49      * Creates a new object map of the same size as the given map and populate
50      * it with the key/attribute pairs found in the map.
51      *
52      * @param map
53      * The entries in the given map will be added to the new map.
54      */

55     public ObjectMap(Map map) {
56         this(map.size());
57         putAll(map);
58     }
59
60     /**
61      * @see Map#clear()
62      */

63     public void clear() {
64         elements = null;
65         count = 0;
66     }
67
68     /**
69      * @see java.lang.Object#clone()
70      */

71     public Object JavaDoc clone() {
72         return new ObjectMap(this);
73     }
74
75     /**
76      * @see Map#containsKey(java.lang.Object)
77      */

78     public boolean containsKey(Object JavaDoc key) {
79         if (elements == null || count == 0)
80             return false;
81         for (int i = 0; i < elements.length; i = i + 2)
82             if (elements[i] != null && elements[i].equals(key))
83                 return true;
84         return false;
85     }
86
87     /**
88      * @see Map#containsValue(java.lang.Object)
89      */

90     public boolean containsValue(Object JavaDoc value) {
91         if (elements == null || count == 0)
92             return false;
93         for (int i = 1; i < elements.length; i = i + 2)
94             if (elements[i] != null && elements[i].equals(value))
95                 return true;
96         return false;
97     }
98
99     /**
100      * @see Map#entrySet()
101      *
102      * Note: This implementation does not conform properly to the
103      * specification in the Map interface. The returned collection will not
104      * be bound to this map and will not remain in sync with this map.
105      */

106     public Set entrySet() {
107         return toHashMap().entrySet();
108     }
109
110     /**
111      * @see Object#equals(java.lang.Object)
112      */

113     public boolean equals(Object JavaDoc o) {
114         if (!(o instanceof Map))
115             return false;
116         Map other = (Map) o;
117         //must be same size
118
if (count != other.size())
119             return false;
120         //keysets must be equal
121
if (!keySet().equals(other.keySet()))
122             return false;
123         //values for each key must be equal
124
for (int i = 0; i < elements.length; i = i + 2) {
125             if (elements[i] != null && (!elements[i + 1].equals(other.get(elements[i]))))
126                 return false;
127         }
128         return true;
129     }
130
131     /**
132      * @see Map#get(java.lang.Object)
133      */

134     public Object JavaDoc get(Object JavaDoc key) {
135         if (elements == null || count == 0)
136             return null;
137         for (int i = 0; i < elements.length; i = i + 2)
138             if (elements[i] != null && elements[i].equals(key))
139                 return elements[i + 1];
140         return null;
141     }
142
143     /**
144      * The capacity of the map has been exceeded, grow the array by GROW_SIZE to
145      * accomodate more entries.
146      */

147     protected void grow() {
148         Object JavaDoc[] expanded = new Object JavaDoc[elements.length + GROW_SIZE];
149         System.arraycopy(elements, 0, expanded, 0, elements.length);
150         elements = expanded;
151     }
152
153     /**
154      * @see Object#hashCode()
155      */

156     public int hashCode() {
157         int hash = 0;
158         for (int i = 0; i < elements.length; i = i + 2) {
159             if (elements[i] != null) {
160                 hash += elements[i].hashCode();
161             }
162         }
163         return hash;
164     }
165
166     /**
167      * @see Map#isEmpty()
168      */

169     public boolean isEmpty() {
170         return count == 0;
171     }
172
173     /**
174      * Returns all keys in this table as an array.
175      */

176     public String JavaDoc[] keys() {
177         String JavaDoc[] result = new String JavaDoc[count];
178         int next = 0;
179         for (int i = 0; i < elements.length; i = i + 2)
180             if (elements[i] != null)
181                 result[next++] = (String JavaDoc) elements[i];
182         return result;
183     }
184
185     /**
186      * @see Map#keySet()
187      *
188      * Note: This implementation does not conform properly to the
189      * specification in the Map interface. The returned collection will not
190      * be bound to this map and will not remain in sync with this map.
191      */

192     public Set keySet() {
193         Set result = new HashSet(size());
194         for (int i = 0; i < elements.length; i = i + 2) {
195             if (elements[i] != null) {
196                 result.add(elements[i]);
197             }
198         }
199         return result;
200     }
201     
202     /**
203      * @see Map#put(java.lang.Object, java.lang.Object)
204      */

205     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
206         if (key == null)
207             throw new NullPointerException JavaDoc();
208         if (value == null)
209             return remove(key);
210
211         // handle the case where we don't have any attributes yet
212
if (elements == null)
213             elements = new Object JavaDoc[DEFAULT_SIZE];
214         if (count == 0) {
215             elements[0] = key;
216             elements[1] = value;
217             count++;
218             return null;
219         }
220
221         int emptyIndex = -1;
222         // replace existing value if it exists
223
for (int i = 0; i < elements.length; i += 2) {
224             if (elements[i] != null) {
225                 if (elements[i].equals(key)) {
226                     Object JavaDoc oldValue = elements[i + 1];
227                     elements[i + 1] = value;
228                     return oldValue;
229                 }
230             } else if (emptyIndex == -1) {
231                 // keep track of the first empty index
232
emptyIndex = i;
233             }
234         }
235         // this will put the emptyIndex greater than the size but
236
// that's ok because we will grow first.
237
if (emptyIndex == -1)
238             emptyIndex = count * 2;
239
240         // otherwise add it to the list of elements.
241
// grow if necessary
242
if (elements.length <= (count * 2))
243             grow();
244         elements[emptyIndex] = key;
245         elements[emptyIndex + 1] = value;
246         count++;
247         return null;
248     }
249
250     /**
251      * @see Map#putAll(java.util.Map)
252      */

253     public void putAll(Map map) {
254         for (Iterator i = map.keySet().iterator(); i.hasNext();) {
255             Object JavaDoc key = i.next();
256             Object JavaDoc value = map.get(key);
257             put(key, value);
258         }
259     }
260
261     /**
262      * @see Map#remove(java.lang.Object)
263      */

264     public Object JavaDoc remove(Object JavaDoc key) {
265         if (elements == null || count == 0)
266             return null;
267         for (int i = 0; i < elements.length; i = i + 2) {
268             if (elements[i] != null && elements[i].equals(key)) {
269                 elements[i] = null;
270                 Object JavaDoc result = elements[i + 1];
271                 elements[i + 1] = null;
272                 count--;
273                 return result;
274             }
275         }
276         return null;
277     }
278
279     /* (non-Javadoc
280      * Method declared on IStringPoolParticipant
281      */

282     public void shareStrings(StringPool set) {
283         //copy elements for thread safety
284
Object JavaDoc[] array = elements;
285         if (array == null)
286             return;
287         for (int i = 0; i < array.length; i++) {
288             Object JavaDoc o = array[i];
289             if (o instanceof String JavaDoc)
290                 array[i] = set.add((String JavaDoc) o);
291         }
292     }
293
294     /**
295      * @see Map#size()
296      */

297     public int size() {
298         return count;
299     }
300
301     /**
302      * Creates a new hash map with the same contents as this map.
303      */

304     private HashMap toHashMap() {
305         HashMap result = new HashMap(size());
306         for (int i = 0; i < elements.length; i = i + 2) {
307             if (elements[i] != null) {
308                 result.put(elements[i], elements[i + 1]);
309             }
310         }
311         return result;
312     }
313
314     /**
315      * @see Map#values()
316      *
317      * Note: This implementation does not conform properly to the
318      * specification in the Map interface. The returned collection will not
319      * be bound to this map and will not remain in sync with this map.
320      */

321     public Collection values() {
322         Set result = new HashSet(size());
323         for (int i = 1; i < elements.length; i = i + 2) {
324             if (elements[i] != null) {
325                 result.add(elements[i]);
326             }
327         }
328         return result;
329     }
330 }
Popular Tags