GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
ArrayHashMap.java
Go to the documentation of this file.
1/**
2 * Copyright 2015 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.common.util;
30
31import java.util.ArrayList;
32import java.util.Collection;
33import java.util.HashMap;
34import java.util.Iterator;
35import java.util.Map;
36import java.util.Set;
37
38/**
39 * {@link HashMap} implementation backed by an {@link ArrayList} to preserve order of values.
40 *
41 * Implementation properties are:
42 * <ul>
43 * <li> Unique elements utilizing {@link java.lang.Object#hashCode()} for O(1) operations, see below.</li>
44 * <li> Java 1.5 compatible</li>
45 * </ul>
46 *
47 * O(1) operations:
48 * <ul>
49 * <li> put new key-value-pair(s) </li>
50 * <li> test for containment </li>
51 * <li> trying to remove non existent elements </li>
52 * </ul>
53 *
54 * O(n) operations:
55 * <ul>
56 * <li> put existing key-value-pair(s) </li>
57 * <li> removing existing elements</li>
58 * </ul>
59 *
60 * For thread safety, the application shall decorate access to instances via
61 * {@link com.jogamp.common.util.locks.RecursiveLock}.
62 *
63*/
64public class ArrayHashMap<K, V>
65 implements Cloneable, Map<K, V>
66{
67 /**
68 * Default load factor: {@value}
69 */
70 public static final float DEFAULT_LOAD_FACTOR = 0.75f;
71 /**
72 * The default initial capacity: {@value}
73 */
74 public static final int DEFAULT_INITIAL_CAPACITY = 16;
75
76 private final HashMap<K,V> map; // key -> object
77 private final ArrayList<V> data; // list of objects
78 private final boolean supportNullValue;
79
80 /**
81 *
82 * @param supportNullValue Use {@code true} for default behavior, i.e. {@code null} can be a valid value.
83 * Use {@code false} if {@code null} is not a valid value,
84 * here {@link #put(Object, Object)} and {@link #remove(Object)} will be optimized.
85 * @param initialCapacity use {@link #DEFAULT_INITIAL_CAPACITY} for default
86 * @param loadFactor use {@link #DEFAULT_LOAD_FACTOR} for default
87 * @see #supportsNullValue()
88 */
89 public ArrayHashMap(final boolean supportNullValue, final int initialCapacity, final float loadFactor) {
90 this.map = new HashMap<K,V>(initialCapacity, loadFactor);
91 this.data = new ArrayList<V>(initialCapacity);
92 this.supportNullValue = supportNullValue;
93 }
94
95 /**
96 * @return a shallow copy of this ArrayHashMap, elements are not copied.
97 */
99 map = new HashMap<K, V>(o.map);
100 data = new ArrayList<V>(o.data);
101 supportNullValue = o.supportNullValue;
102 }
103
104 /**
105 * Returns {@code true} for default behavior, i.e. {@code null} can be a valid value.
106 * <p>
107 * Returns {@code false} if {@code null} is not a valid value,
108 * here {@link #put(Object, Object)} and {@link #remove(Object)} are optimized operations.
109 * </p>
110 * @see #ArrayHashMap(boolean, int, float)
111 */
112 public final boolean supportsNullValue() { return supportNullValue; }
113
114 //
115 // Cloneable
116 //
117
118 /**
119 * Implementation uses {@link #ArrayHashMap(ArrayHashMap)}.
120 * @return a shallow copy of this ArrayHashMap, elements are not copied.
121 */
122 @Override
123 public final Object clone() {
124 return new ArrayHashMap<K, V>(this);
125 }
126
127 /**
128 * Returns this object ordered ArrayList. Use w/ care, it's not a copy.
129 * @see #toArrayList()
130 */
131 public final ArrayList<V> getData() { return data; }
132
133 /**
134 * @return a shallow copy of this ArrayHashMap's ArrayList, elements are not copied.
135 * @see #getData()
136 */
137 public final ArrayList<V> toArrayList() {
138 return new ArrayList<V>(data);
139 }
140
141 /** Returns this object hash map. Use w/ care, it's not a copy. */
142 public final HashMap<K,V> getMap() { return map; }
143
144 @Override
145 public final String toString() { return data.toString(); }
146
147 //
148 // Map
149 //
150
151 @Override
152 public final void clear() {
153 data.clear();
154 map.clear();
155 }
156
157 @Override
158 public Set<K> keySet() {
159 return map.keySet();
160 }
161
162 /**
163 * {@inheritDoc}
164 * <p>
165 * See {@link #getData()} and {@link #toArrayList()}.
166 * </p>
167 * @see #getData()
168 * @see #toArrayList()
169 */
170 @Override
171 public Collection<V> values() {
172 return map.values();
173 }
174
175 @Override
176 public Set<java.util.Map.Entry<K, V>> entrySet() {
177 return map.entrySet();
178 }
179
180 @Override
181 public final V get(final Object key) {
182 return map.get(key);
183 }
184
185 /**
186 * {@inheritDoc}
187 * <p>
188 * This is an O(1) operation, in case the key does not exist,
189 * otherwise O(n).
190 * </p>
191 * @throws NullPointerException if {@code value} is {@code null} but {@link #supportsNullValue()} == {@code false}
192 */
193 @Override
194 public final V put(final K key, final V value) throws NullPointerException {
195 final V oldValue;
196 if( supportNullValue ) {
197 // slow path
198 final boolean exists = map.containsKey(key);
199 if(!exists) {
200 // !exists
201 if( null != ( oldValue = map.put(key, value) ) ) {
202 // slips a valid null ..
203 throw new InternalError("Already existing, but checked before: "+key+" -> "+oldValue);
204 }
205 } else {
206 // exists
207 oldValue = map.put(key, value);
208 if( !data.remove(oldValue) ) {
209 throw new InternalError("Already existing, but not in list: "+oldValue);
210 }
211 }
212 } else {
213 checkNullValue(value);
214 // fast path
215 if( null != ( oldValue = map.put(key, value) ) ) {
216 // exists
217 if( !data.remove(oldValue) ) {
218 throw new InternalError("Already existing, but not in list: "+oldValue);
219 }
220 }
221 }
222 if(!data.add(value)) {
223 throw new InternalError("Couldn't add value to list: "+value);
224 }
225 return oldValue;
226 }
227
228 @Override
229 public void putAll(final Map<? extends K, ? extends V> m) {
230 for (final Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
231 final Map.Entry<? extends K, ? extends V> e = i.next();
232 put(e.getKey(), e.getValue());
233 }
234 }
235
236 /**
237 * {@inheritDoc}
238 * <p>
239 * This is an O(1) operation, in case the key does not exist,
240 * otherwise O(n).
241 * </p>
242 */
243 @Override
244 public final V remove(final Object key) {
245 if( supportNullValue ) {
246 if( map.containsKey(key) ) {
247 // exists
248 final V oldValue = map.remove(key);
249 if ( !data.remove(oldValue) ) {
250 throw new InternalError("Couldn't remove prev mapped pair: "+key+" -> "+oldValue);
251 }
252 return oldValue;
253 }
254 } else {
255 final V oldValue;
256 if ( null != (oldValue = map.remove(key) ) ) {
257 // exists
258 if ( !data.remove(oldValue) ) {
259 throw new InternalError("Couldn't remove prev mapped pair: "+key+" -> "+oldValue);
260 }
261 }
262 return oldValue;
263 }
264 return null;
265 }
266
267 @Override
268 public final boolean containsKey(final Object key) {
269 return map.containsKey(key);
270 }
271
272 @Override
273 public boolean containsValue(final Object value) {
274 return map.containsValue(value);
275 }
276
277 @Override
278 public final boolean equals(final Object arrayHashMap) {
279 if ( !(arrayHashMap instanceof ArrayHashMap) ) {
280 return false;
281 }
282 return map.equals(((ArrayHashMap<?,?>)arrayHashMap).map);
283 }
284
285 @Override
286 public final int hashCode() {
287 return map.hashCode();
288 }
289
290 @Override
291 public final boolean isEmpty() {
292 return data.isEmpty();
293 }
294
295 @Override
296 public final int size() {
297 return data.size();
298 }
299
300 private static final void checkNullValue(final Object value) throws NullPointerException {
301 if( null == value ) {
302 throw new NullPointerException("Null value not supported");
303 }
304 }
305}
HashMap implementation backed by an ArrayList to preserve order of values.
final Object clone()
Implementation uses ArrayHashMap(ArrayHashMap).
final boolean containsKey(final Object key)
final boolean supportsNullValue()
Returns true for default behavior, i.e.
boolean containsValue(final Object value)
static final int DEFAULT_INITIAL_CAPACITY
The default initial capacity: {@value}.
final boolean equals(final Object arrayHashMap)
static final float DEFAULT_LOAD_FACTOR
Default load factor: {@value}.
Set< java.util.Map.Entry< K, V > > entrySet()
final ArrayList< V > getData()
Returns this object ordered ArrayList.
final ArrayList< V > toArrayList()
ArrayHashMap(final ArrayHashMap< K, V > o)
void putAll(final Map<? extends K, ? extends V > m)
final HashMap< K, V > getMap()
Returns this object hash map.
ArrayHashMap(final boolean supportNullValue, final int initialCapacity, final float loadFactor)
final V put(final K key, final V value)