Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/PojavLauncher
Path: blob/v3_openjdk/jre_lwjgl3glfw/src/main/java/android/util/ArrayMap.java
2129 views
1
/*
2
* Copyright (C) 2013 The Android Open Source Project
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
* http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
16
17
package android.util;
18
19
import java.util.Collection;
20
import java.util.Map;
21
import java.util.Set;
22
23
/**
24
* ArrayMap is a generic key->value mapping data structure that is
25
* designed to be more memory efficient than a traditional {@link java.util.HashMap}.
26
* It keeps its mappings in an array data structure -- an integer array of hash
27
* codes for each item, and an Object array of the key/value pairs. This allows it to
28
* avoid having to create an extra object for every entry put in to the map, and it
29
* also tries to control the growth of the size of these arrays more aggressively
30
* (since growing them only requires copying the entries in the array, not rebuilding
31
* a hash map).
32
*
33
* <p>Note that this implementation is not intended to be appropriate for data structures
34
* that may contain large numbers of items. It is generally slower than a traditional
35
* HashMap, since lookups require a binary search and adds and removes require inserting
36
* and deleting entries in the array. For containers holding up to hundreds of items,
37
* the performance difference is not significant, less than 50%.</p>
38
*
39
* <p>Because this container is intended to better balance memory use, unlike most other
40
* standard Java containers it will shrink its array as items are removed from it. Currently
41
* you have no control over this shrinking -- if you set a capacity and then remove an
42
* item, it may reduce the capacity to better match the current size. In the future an
43
* explicit call to set the capacity should turn off this aggressive shrinking behavior.</p>
44
*/
45
public final class ArrayMap<K, V> implements Map<K, V> {
46
private static final boolean DEBUG = false;
47
private static final String TAG = "ArrayMap";
48
49
/**
50
* The minimum amount by which the capacity of a ArrayMap will increase.
51
* This is tuned to be relatively space-efficient.
52
*/
53
private static final int BASE_SIZE = 4;
54
55
/**
56
* Maximum number of entries to have in array caches.
57
*/
58
private static final int CACHE_SIZE = 10;
59
60
/**
61
* Special hash array value that indicates the container is immutable.
62
*/
63
static final int[] EMPTY_IMMUTABLE_INTS = new int[0];
64
65
/**
66
* @hide Special immutable empty ArrayMap.
67
*/
68
public static final ArrayMap EMPTY = new ArrayMap(true);
69
70
/**
71
* Caches of small array objects to avoid spamming garbage. The cache
72
* Object[] variable is a pointer to a linked list of array objects.
73
* The first entry in the array is a pointer to the next array in the
74
* list; the second entry is a pointer to the int[] hash code array for it.
75
*/
76
static Object[] mBaseCache;
77
static int mBaseCacheSize;
78
static Object[] mTwiceBaseCache;
79
static int mTwiceBaseCacheSize;
80
81
int[] mHashes;
82
Object[] mArray;
83
int mSize;
84
MapCollections<K, V> mCollections;
85
86
int indexOf(Object key, int hash) {
87
final int N = mSize;
88
89
// Important fast case: if nothing is in here, nothing to look for.
90
if (N == 0) {
91
return ~0;
92
}
93
94
int index = ContainerHelpers.binarySearch(mHashes, N, hash);
95
96
// If the hash code wasn't found, then we have no entry for this key.
97
if (index < 0) {
98
return index;
99
}
100
101
// If the key at the returned index matches, that's what we want.
102
if (key.equals(mArray[index<<1])) {
103
return index;
104
}
105
106
// Search for a matching key after the index.
107
int end;
108
for (end = index + 1; end < N && mHashes[end] == hash; end++) {
109
if (key.equals(mArray[end << 1])) return end;
110
}
111
112
// Search for a matching key before the index.
113
for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {
114
if (key.equals(mArray[i << 1])) return i;
115
}
116
117
// Key not found -- return negative value indicating where a
118
// new entry for this key should go. We use the end of the
119
// hash chain to reduce the number of array entries that will
120
// need to be copied when inserting.
121
return ~end;
122
}
123
124
int indexOfNull() {
125
final int N = mSize;
126
127
// Important fast case: if nothing is in here, nothing to look for.
128
if (N == 0) {
129
return ~0;
130
}
131
132
int index = ContainerHelpers.binarySearch(mHashes, N, 0);
133
134
// If the hash code wasn't found, then we have no entry for this key.
135
if (index < 0) {
136
return index;
137
}
138
139
// If the key at the returned index matches, that's what we want.
140
if (null == mArray[index<<1]) {
141
return index;
142
}
143
144
// Search for a matching key after the index.
145
int end;
146
for (end = index + 1; end < N && mHashes[end] == 0; end++) {
147
if (null == mArray[end << 1]) return end;
148
}
149
150
// Search for a matching key before the index.
151
for (int i = index - 1; i >= 0 && mHashes[i] == 0; i--) {
152
if (null == mArray[i << 1]) return i;
153
}
154
155
// Key not found -- return negative value indicating where a
156
// new entry for this key should go. We use the end of the
157
// hash chain to reduce the number of array entries that will
158
// need to be copied when inserting.
159
return ~end;
160
}
161
162
private void allocArrays(final int size) {
163
if (mHashes == EMPTY_IMMUTABLE_INTS) {
164
throw new UnsupportedOperationException("ArrayMap is immutable");
165
}
166
if (size == (BASE_SIZE*2)) {
167
synchronized (ArrayMap.class) {
168
if (mTwiceBaseCache != null) {
169
final Object[] array = mTwiceBaseCache;
170
mArray = array;
171
mTwiceBaseCache = (Object[])array[0];
172
mHashes = (int[])array[1];
173
array[0] = array[1] = null;
174
mTwiceBaseCacheSize--;
175
if (DEBUG) System.out.println("Retrieving 2x cache " + mHashes
176
+ " now have " + mTwiceBaseCacheSize + " entries");
177
return;
178
}
179
}
180
} else if (size == BASE_SIZE) {
181
synchronized (ArrayMap.class) {
182
if (mBaseCache != null) {
183
final Object[] array = mBaseCache;
184
mArray = array;
185
mBaseCache = (Object[])array[0];
186
mHashes = (int[])array[1];
187
array[0] = array[1] = null;
188
mBaseCacheSize--;
189
if (DEBUG) System.out.println("Retrieving 1x cache " + mHashes
190
+ " now have " + mBaseCacheSize + " entries");
191
return;
192
}
193
}
194
}
195
196
mHashes = new int[size];
197
mArray = new Object[size<<1];
198
}
199
200
private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
201
if (hashes.length == (BASE_SIZE*2)) {
202
synchronized (ArrayMap.class) {
203
if (mTwiceBaseCacheSize < CACHE_SIZE) {
204
array[0] = mTwiceBaseCache;
205
array[1] = hashes;
206
for (int i=(size<<1)-1; i>=2; i--) {
207
array[i] = null;
208
}
209
mTwiceBaseCache = array;
210
mTwiceBaseCacheSize++;
211
if (DEBUG) System.out.println("Storing 2x cache " + array
212
+ " now have " + mTwiceBaseCacheSize + " entries");
213
}
214
}
215
} else if (hashes.length == BASE_SIZE) {
216
synchronized (ArrayMap.class) {
217
if (mBaseCacheSize < CACHE_SIZE) {
218
array[0] = mBaseCache;
219
array[1] = hashes;
220
for (int i=(size<<1)-1; i>=2; i--) {
221
array[i] = null;
222
}
223
mBaseCache = array;
224
mBaseCacheSize++;
225
if (DEBUG) System.out.println("Storing 1x cache " + array
226
+ " now have " + mBaseCacheSize + " entries");
227
}
228
}
229
}
230
}
231
232
/**
233
* Create a new empty ArrayMap. The default capacity of an array map is 0, and
234
* will grow once items are added to it.
235
*/
236
public ArrayMap() {
237
mHashes = EmptyArray.INT;
238
mArray = EmptyArray.OBJECT;
239
mSize = 0;
240
}
241
242
/**
243
* Create a new ArrayMap with a given initial capacity.
244
*/
245
public ArrayMap(int capacity) {
246
if (capacity == 0) {
247
mHashes = EmptyArray.INT;
248
mArray = EmptyArray.OBJECT;
249
} else {
250
allocArrays(capacity);
251
}
252
mSize = 0;
253
}
254
255
private ArrayMap(boolean immutable) {
256
// If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
257
// instance instead of the usual EmptyArray.INT. The reference
258
// is checked later to see if the array is allowed to grow.
259
mHashes = immutable ? EMPTY_IMMUTABLE_INTS : EmptyArray.INT;
260
mArray = EmptyArray.OBJECT;
261
mSize = 0;
262
}
263
264
/**
265
* Create a new ArrayMap with the mappings from the given ArrayMap.
266
*/
267
public ArrayMap(ArrayMap<K, V> map) {
268
this();
269
if (map != null) {
270
putAll(map);
271
}
272
}
273
274
/**
275
* Make the array map empty. All storage is released.
276
*/
277
@Override
278
public void clear() {
279
if (mSize > 0) {
280
freeArrays(mHashes, mArray, mSize);
281
mHashes = EmptyArray.INT;
282
mArray = EmptyArray.OBJECT;
283
mSize = 0;
284
}
285
}
286
287
/**
288
* @hide
289
* Like {@link #clear}, but doesn't reduce the capacity of the ArrayMap.
290
*/
291
public void erase() {
292
if (mSize > 0) {
293
final int N = mSize<<1;
294
final Object[] array = mArray;
295
for (int i=0; i<N; i++) {
296
array[i] = null;
297
}
298
mSize = 0;
299
}
300
}
301
302
/**
303
* Ensure the array map can hold at least <var>minimumCapacity</var>
304
* items.
305
*/
306
public void ensureCapacity(int minimumCapacity) {
307
if (mHashes.length < minimumCapacity) {
308
final int[] ohashes = mHashes;
309
final Object[] oarray = mArray;
310
allocArrays(minimumCapacity);
311
if (mSize > 0) {
312
System.arraycopy(ohashes, 0, mHashes, 0, mSize);
313
System.arraycopy(oarray, 0, mArray, 0, mSize<<1);
314
}
315
freeArrays(ohashes, oarray, mSize);
316
}
317
}
318
319
/**
320
* Check whether a key exists in the array.
321
*
322
* @param key The key to search for.
323
* @return Returns true if the key exists, else false.
324
*/
325
@Override
326
public boolean containsKey(Object key) {
327
return indexOfKey(key) >= 0;
328
}
329
330
/**
331
* Returns the index of a key in the set.
332
*
333
* @param key The key to search for.
334
* @return Returns the index of the key if it exists, else a negative integer.
335
*/
336
public int indexOfKey(Object key) {
337
return key == null ? indexOfNull() : indexOf(key, key.hashCode());
338
}
339
340
int indexOfValue(Object value) {
341
final int N = mSize*2;
342
final Object[] array = mArray;
343
if (value == null) {
344
for (int i=1; i<N; i+=2) {
345
if (array[i] == null) {
346
return i>>1;
347
}
348
}
349
} else {
350
for (int i=1; i<N; i+=2) {
351
if (value.equals(array[i])) {
352
return i>>1;
353
}
354
}
355
}
356
return -1;
357
}
358
359
/**
360
* Check whether a value exists in the array. This requires a linear search
361
* through the entire array.
362
*
363
* @param value The value to search for.
364
* @return Returns true if the value exists, else false.
365
*/
366
@Override
367
public boolean containsValue(Object value) {
368
return indexOfValue(value) >= 0;
369
}
370
371
/**
372
* Retrieve a value from the array.
373
* @param key The key of the value to retrieve.
374
* @return Returns the value associated with the given key,
375
* or null if there is no such key.
376
*/
377
@Override
378
public V get(Object key) {
379
final int index = indexOfKey(key);
380
return index >= 0 ? (V)mArray[(index<<1)+1] : null;
381
}
382
383
/**
384
* Return the key at the given index in the array.
385
* @param index The desired index, must be between 0 and {@link #size()}-1.
386
* @return Returns the key stored at the given index.
387
*/
388
public K keyAt(int index) {
389
return (K)mArray[index << 1];
390
}
391
392
/**
393
* Return the value at the given index in the array.
394
* @param index The desired index, must be between 0 and {@link #size()}-1.
395
* @return Returns the value stored at the given index.
396
*/
397
public V valueAt(int index) {
398
return (V)mArray[(index << 1) + 1];
399
}
400
401
/**
402
* Set the value at a given index in the array.
403
* @param index The desired index, must be between 0 and {@link #size()}-1.
404
* @param value The new value to store at this index.
405
* @return Returns the previous value at the given index.
406
*/
407
public V setValueAt(int index, V value) {
408
index = (index << 1) + 1;
409
V old = (V)mArray[index];
410
mArray[index] = value;
411
return old;
412
}
413
414
/**
415
* Return true if the array map contains no items.
416
*/
417
@Override
418
public boolean isEmpty() {
419
return mSize <= 0;
420
}
421
422
/**
423
* Add a new value to the array map.
424
* @param key The key under which to store the value. If
425
* this key already exists in the array, its value will be replaced.
426
* @param value The value to store for the given key.
427
* @return Returns the old value that was stored for the given key, or null if there
428
* was no such key.
429
*/
430
@Override
431
public V put(K key, V value) {
432
final int hash;
433
int index;
434
if (key == null) {
435
hash = 0;
436
index = indexOfNull();
437
} else {
438
hash = key.hashCode();
439
index = indexOf(key, hash);
440
}
441
if (index >= 0) {
442
index = (index<<1) + 1;
443
final V old = (V)mArray[index];
444
mArray[index] = value;
445
return old;
446
}
447
448
index = ~index;
449
if (mSize >= mHashes.length) {
450
final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1))
451
: (mSize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);
452
453
if (DEBUG) System.out.println("put: grow from " + mHashes.length + " to " + n);
454
455
final int[] ohashes = mHashes;
456
final Object[] oarray = mArray;
457
allocArrays(n);
458
459
if (mHashes.length > 0) {
460
if (DEBUG) System.out.println("put: copy 0-" + mSize + " to 0");
461
System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);
462
System.arraycopy(oarray, 0, mArray, 0, oarray.length);
463
}
464
465
freeArrays(ohashes, oarray, mSize);
466
}
467
468
if (index < mSize) {
469
if (DEBUG) System.out.println("put: move " + index + "-" + (mSize-index)
470
+ " to " + (index+1));
471
System.arraycopy(mHashes, index, mHashes, index + 1, mSize - index);
472
System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);
473
}
474
475
mHashes[index] = hash;
476
mArray[index<<1] = key;
477
mArray[(index<<1)+1] = value;
478
mSize++;
479
return null;
480
}
481
482
/**
483
* Special fast path for appending items to the end of the array without validation.
484
* The array must already be large enough to contain the item.
485
* @hide
486
*/
487
public void append(K key, V value) {
488
int index = mSize;
489
final int hash = key == null ? 0 : key.hashCode();
490
if (index >= mHashes.length) {
491
throw new IllegalStateException("Array is full");
492
}
493
if (index > 0 && mHashes[index-1] > hash) {
494
RuntimeException e = new RuntimeException("here");
495
e.fillInStackTrace();
496
System.out.println("New hash " + hash
497
+ " is before end of array hash " + mHashes[index-1]
498
+ " at index " + index + " key " + key);
499
e.printStackTrace();
500
put(key, value);
501
return;
502
}
503
mSize = index+1;
504
mHashes[index] = hash;
505
index <<= 1;
506
mArray[index] = key;
507
mArray[index+1] = value;
508
}
509
510
/**
511
* The use of the {@link #append} function can result in invalid array maps, in particular
512
* an array map where the same key appears multiple times. This function verifies that
513
* the array map is valid, throwing IllegalArgumentException if a problem is found. The
514
* main use for this method is validating an array map after unpacking from an IPC, to
515
* protect against malicious callers.
516
* @hide
517
*/
518
public void validate() {
519
final int N = mSize;
520
if (N <= 1) {
521
// There can't be dups.
522
return;
523
}
524
int basehash = mHashes[0];
525
int basei = 0;
526
for (int i=1; i<N; i++) {
527
int hash = mHashes[i];
528
if (hash != basehash) {
529
basehash = hash;
530
basei = i;
531
continue;
532
}
533
// We are in a run of entries with the same hash code. Go backwards through
534
// the array to see if any keys are the same.
535
final Object cur = mArray[i<<1];
536
for (int j=i-1; j>=basei; j--) {
537
final Object prev = mArray[j<<1];
538
if (cur == prev) {
539
throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur);
540
}
541
if (cur != null && prev != null && cur.equals(prev)) {
542
throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur);
543
}
544
}
545
}
546
}
547
548
/**
549
* Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var>
550
* @param array The array whose contents are to be retrieved.
551
*/
552
public void putAll(ArrayMap<? extends K, ? extends V> array) {
553
final int N = array.mSize;
554
ensureCapacity(mSize + N);
555
if (mSize == 0) {
556
if (N > 0) {
557
System.arraycopy(array.mHashes, 0, mHashes, 0, N);
558
System.arraycopy(array.mArray, 0, mArray, 0, N<<1);
559
mSize = N;
560
}
561
} else {
562
for (int i=0; i<N; i++) {
563
put(array.keyAt(i), array.valueAt(i));
564
}
565
}
566
}
567
568
/**
569
* Remove an existing key from the array map.
570
* @param key The key of the mapping to remove.
571
* @return Returns the value that was stored under the key, or null if there
572
* was no such key.
573
*/
574
@Override
575
public V remove(Object key) {
576
final int index = indexOfKey(key);
577
if (index >= 0) {
578
return removeAt(index);
579
}
580
581
return null;
582
}
583
584
/**
585
* Remove the key/value mapping at the given index.
586
* @param index The desired index, must be between 0 and {@link #size()}-1.
587
* @return Returns the value that was stored at this index.
588
*/
589
public V removeAt(int index) {
590
final Object old = mArray[(index << 1) + 1];
591
if (mSize <= 1) {
592
// Now empty.
593
if (DEBUG) System.out.println("remove: shrink from " + mHashes.length + " to 0");
594
freeArrays(mHashes, mArray, mSize);
595
mHashes = EmptyArray.INT;
596
mArray = EmptyArray.OBJECT;
597
mSize = 0;
598
} else {
599
if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
600
// Shrunk enough to reduce size of arrays. We don't allow it to
601
// shrink smaller than (BASE_SIZE*2) to avoid flapping between
602
// that and BASE_SIZE.
603
final int n = mSize > (BASE_SIZE*2) ? (mSize + (mSize>>1)) : (BASE_SIZE*2);
604
605
if (DEBUG) System.out.println("remove: shrink from " + mHashes.length + " to " + n);
606
607
final int[] ohashes = mHashes;
608
final Object[] oarray = mArray;
609
allocArrays(n);
610
611
mSize--;
612
if (index > 0) {
613
if (DEBUG) System.out.println("remove: copy from 0-" + index + " to 0");
614
System.arraycopy(ohashes, 0, mHashes, 0, index);
615
System.arraycopy(oarray, 0, mArray, 0, index << 1);
616
}
617
if (index < mSize) {
618
if (DEBUG) System.out.println("remove: copy from " + (index+1) + "-" + mSize
619
+ " to " + index);
620
System.arraycopy(ohashes, index + 1, mHashes, index, mSize - index);
621
System.arraycopy(oarray, (index + 1) << 1, mArray, index << 1,
622
(mSize - index) << 1);
623
}
624
} else {
625
mSize--;
626
if (index < mSize) {
627
if (DEBUG) System.out.println("remove: move " + (index+1) + "-" + mSize
628
+ " to " + index);
629
System.arraycopy(mHashes, index + 1, mHashes, index, mSize - index);
630
System.arraycopy(mArray, (index + 1) << 1, mArray, index << 1,
631
(mSize - index) << 1);
632
}
633
mArray[mSize << 1] = null;
634
mArray[(mSize << 1) + 1] = null;
635
}
636
}
637
return (V)old;
638
}
639
640
/**
641
* Return the number of items in this array map.
642
*/
643
@Override
644
public int size() {
645
return mSize;
646
}
647
648
/**
649
* {@inheritDoc}
650
*
651
* <p>This implementation returns false if the object is not a map, or
652
* if the maps have different sizes. Otherwise, for each key in this map,
653
* values of both maps are compared. If the values for any key are not
654
* equal, the method returns false, otherwise it returns true.
655
*/
656
@Override
657
public boolean equals(Object object) {
658
if (this == object) {
659
return true;
660
}
661
if (object instanceof Map) {
662
Map<?, ?> map = (Map<?, ?>) object;
663
if (size() != map.size()) {
664
return false;
665
}
666
667
try {
668
for (int i=0; i<mSize; i++) {
669
K key = keyAt(i);
670
V mine = valueAt(i);
671
Object theirs = map.get(key);
672
if (mine == null) {
673
if (theirs != null || !map.containsKey(key)) {
674
return false;
675
}
676
} else if (!mine.equals(theirs)) {
677
return false;
678
}
679
}
680
} catch (NullPointerException ignored) {
681
return false;
682
} catch (ClassCastException ignored) {
683
return false;
684
}
685
return true;
686
}
687
return false;
688
}
689
690
/**
691
* {@inheritDoc}
692
*/
693
@Override
694
public int hashCode() {
695
final int[] hashes = mHashes;
696
final Object[] array = mArray;
697
int result = 0;
698
for (int i = 0, v = 1, s = mSize; i < s; i++, v+=2) {
699
Object value = array[v];
700
result += hashes[i] ^ (value == null ? 0 : value.hashCode());
701
}
702
return result;
703
}
704
705
/**
706
* {@inheritDoc}
707
*
708
* <p>This implementation composes a string by iterating over its mappings. If
709
* this map contains itself as a key or a value, the string "(this Map)"
710
* will appear in its place.
711
*/
712
@Override
713
public String toString() {
714
if (isEmpty()) {
715
return "{}";
716
}
717
718
StringBuilder buffer = new StringBuilder(mSize * 28);
719
buffer.append('{');
720
for (int i=0; i<mSize; i++) {
721
if (i > 0) {
722
buffer.append(", ");
723
}
724
Object key = keyAt(i);
725
if (key != this) {
726
buffer.append(key);
727
} else {
728
buffer.append("(this Map)");
729
}
730
buffer.append('=');
731
Object value = valueAt(i);
732
if (value != this) {
733
buffer.append(value);
734
} else {
735
buffer.append("(this Map)");
736
}
737
}
738
buffer.append('}');
739
return buffer.toString();
740
}
741
742
// ------------------------------------------------------------------------
743
// Interop with traditional Java containers. Not as efficient as using
744
// specialized collection APIs.
745
// ------------------------------------------------------------------------
746
747
private MapCollections<K, V> getCollection() {
748
if (mCollections == null) {
749
mCollections = new MapCollections<K, V>() {
750
@Override
751
protected int colGetSize() {
752
return mSize;
753
}
754
755
@Override
756
protected Object colGetEntry(int index, int offset) {
757
return mArray[(index<<1) + offset];
758
}
759
760
@Override
761
protected int colIndexOfKey(Object key) {
762
return indexOfKey(key);
763
}
764
765
@Override
766
protected int colIndexOfValue(Object value) {
767
return indexOfValue(value);
768
}
769
770
@Override
771
protected Map<K, V> colGetMap() {
772
return ArrayMap.this;
773
}
774
775
@Override
776
protected void colPut(K key, V value) {
777
put(key, value);
778
}
779
780
@Override
781
protected V colSetValue(int index, V value) {
782
return setValueAt(index, value);
783
}
784
785
@Override
786
protected void colRemoveAt(int index) {
787
removeAt(index);
788
}
789
790
@Override
791
protected void colClear() {
792
clear();
793
}
794
};
795
}
796
return mCollections;
797
}
798
799
/**
800
* Determine if the array map contains all of the keys in the given collection.
801
* @param collection The collection whose contents are to be checked against.
802
* @return Returns true if this array map contains a key for every entry
803
* in <var>collection</var>, else returns false.
804
*/
805
public boolean containsAll(Collection<?> collection) {
806
return MapCollections.containsAllHelper(this, collection);
807
}
808
809
/**
810
* Perform a {@link #put(Object, Object)} of all key/value pairs in <var>map</var>
811
* @param map The map whose contents are to be retrieved.
812
*/
813
@Override
814
public void putAll(Map<? extends K, ? extends V> map) {
815
ensureCapacity(mSize + map.size());
816
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
817
put(entry.getKey(), entry.getValue());
818
}
819
}
820
821
/**
822
* Remove all keys in the array map that exist in the given collection.
823
* @param collection The collection whose contents are to be used to remove keys.
824
* @return Returns true if any keys were removed from the array map, else false.
825
*/
826
public boolean removeAll(Collection<?> collection) {
827
return MapCollections.removeAllHelper(this, collection);
828
}
829
830
/**
831
* Remove all keys in the array map that do <b>not</b> exist in the given collection.
832
* @param collection The collection whose contents are to be used to determine which
833
* keys to keep.
834
* @return Returns true if any keys were removed from the array map, else false.
835
*/
836
public boolean retainAll(Collection<?> collection) {
837
return MapCollections.retainAllHelper(this, collection);
838
}
839
840
/**
841
* Return a {@link java.util.Set} for iterating over and interacting with all mappings
842
* in the array map.
843
*
844
* <p><b>Note:</b> this is a very inefficient way to access the array contents, it
845
* requires generating a number of temporary objects and allocates additional state
846
* information associated with the container that will remain for the life of the container.</p>
847
*
848
* <p><b>Note:</b></p> the semantics of this
849
* Set are subtly different than that of a {@link java.util.HashMap}: most important,
850
* the {@link java.util.Map.Entry Map.Entry} object returned by its iterator is a single
851
* object that exists for the entire iterator, so you can <b>not</b> hold on to it
852
* after calling {@link java.util.Iterator#next() Iterator.next}.</p>
853
*/
854
@Override
855
public Set<Map.Entry<K, V>> entrySet() {
856
return getCollection().getEntrySet();
857
}
858
859
/**
860
* Return a {@link java.util.Set} for iterating over and interacting with all keys
861
* in the array map.
862
*
863
* <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
864
* requires generating a number of temporary objects and allocates additional state
865
* information associated with the container that will remain for the life of the container.</p>
866
*/
867
@Override
868
public Set<K> keySet() {
869
return getCollection().getKeySet();
870
}
871
872
/**
873
* Return a {@link java.util.Collection} for iterating over and interacting with all values
874
* in the array map.
875
*
876
* <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
877
* requires generating a number of temporary objects and allocates additional state
878
* information associated with the container that will remain for the life of the container.</p>
879
*/
880
@Override
881
public Collection<V> values() {
882
return getCollection().getValues();
883
}
884
}
885
886