Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/util/EnumMap.java
38829 views
1
/*
2
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.util;
27
28
import java.util.Map.Entry;
29
import sun.misc.SharedSecrets;
30
31
/**
32
* A specialized {@link Map} implementation for use with enum type keys. All
33
* of the keys in an enum map must come from a single enum type that is
34
* specified, explicitly or implicitly, when the map is created. Enum maps
35
* are represented internally as arrays. This representation is extremely
36
* compact and efficient.
37
*
38
* <p>Enum maps are maintained in the <i>natural order</i> of their keys
39
* (the order in which the enum constants are declared). This is reflected
40
* in the iterators returned by the collections views ({@link #keySet()},
41
* {@link #entrySet()}, and {@link #values()}).
42
*
43
* <p>Iterators returned by the collection views are <i>weakly consistent</i>:
44
* they will never throw {@link ConcurrentModificationException} and they may
45
* or may not show the effects of any modifications to the map that occur while
46
* the iteration is in progress.
47
*
48
* <p>Null keys are not permitted. Attempts to insert a null key will
49
* throw {@link NullPointerException}. Attempts to test for the
50
* presence of a null key or to remove one will, however, function properly.
51
* Null values are permitted.
52
53
* <P>Like most collection implementations <tt>EnumMap</tt> is not
54
* synchronized. If multiple threads access an enum map concurrently, and at
55
* least one of the threads modifies the map, it should be synchronized
56
* externally. This is typically accomplished by synchronizing on some
57
* object that naturally encapsulates the enum map. If no such object exists,
58
* the map should be "wrapped" using the {@link Collections#synchronizedMap}
59
* method. This is best done at creation time, to prevent accidental
60
* unsynchronized access:
61
*
62
* <pre>
63
* Map&lt;EnumKey, V&gt; m
64
* = Collections.synchronizedMap(new EnumMap&lt;EnumKey, V&gt;(...));
65
* </pre>
66
*
67
* <p>Implementation note: All basic operations execute in constant time.
68
* They are likely (though not guaranteed) to be faster than their
69
* {@link HashMap} counterparts.
70
*
71
* <p>This class is a member of the
72
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
73
* Java Collections Framework</a>.
74
*
75
* @author Josh Bloch
76
* @see EnumSet
77
* @since 1.5
78
*/
79
public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
80
implements java.io.Serializable, Cloneable
81
{
82
/**
83
* The <tt>Class</tt> object for the enum type of all the keys of this map.
84
*
85
* @serial
86
*/
87
private final Class<K> keyType;
88
89
/**
90
* All of the values comprising K. (Cached for performance.)
91
*/
92
private transient K[] keyUniverse;
93
94
/**
95
* Array representation of this map. The ith element is the value
96
* to which universe[i] is currently mapped, or null if it isn't
97
* mapped to anything, or NULL if it's mapped to null.
98
*/
99
private transient Object[] vals;
100
101
/**
102
* The number of mappings in this map.
103
*/
104
private transient int size = 0;
105
106
/**
107
* Distinguished non-null value for representing null values.
108
*/
109
private static final Object NULL = new Object() {
110
public int hashCode() {
111
return 0;
112
}
113
114
public String toString() {
115
return "java.util.EnumMap.NULL";
116
}
117
};
118
119
private Object maskNull(Object value) {
120
return (value == null ? NULL : value);
121
}
122
123
@SuppressWarnings("unchecked")
124
private V unmaskNull(Object value) {
125
return (V)(value == NULL ? null : value);
126
}
127
128
private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
129
130
/**
131
* Creates an empty enum map with the specified key type.
132
*
133
* @param keyType the class object of the key type for this enum map
134
* @throws NullPointerException if <tt>keyType</tt> is null
135
*/
136
public EnumMap(Class<K> keyType) {
137
this.keyType = keyType;
138
keyUniverse = getKeyUniverse(keyType);
139
vals = new Object[keyUniverse.length];
140
}
141
142
/**
143
* Creates an enum map with the same key type as the specified enum
144
* map, initially containing the same mappings (if any).
145
*
146
* @param m the enum map from which to initialize this enum map
147
* @throws NullPointerException if <tt>m</tt> is null
148
*/
149
public EnumMap(EnumMap<K, ? extends V> m) {
150
keyType = m.keyType;
151
keyUniverse = m.keyUniverse;
152
vals = m.vals.clone();
153
size = m.size;
154
}
155
156
/**
157
* Creates an enum map initialized from the specified map. If the
158
* specified map is an <tt>EnumMap</tt> instance, this constructor behaves
159
* identically to {@link #EnumMap(EnumMap)}. Otherwise, the specified map
160
* must contain at least one mapping (in order to determine the new
161
* enum map's key type).
162
*
163
* @param m the map from which to initialize this enum map
164
* @throws IllegalArgumentException if <tt>m</tt> is not an
165
* <tt>EnumMap</tt> instance and contains no mappings
166
* @throws NullPointerException if <tt>m</tt> is null
167
*/
168
public EnumMap(Map<K, ? extends V> m) {
169
if (m instanceof EnumMap) {
170
EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
171
keyType = em.keyType;
172
keyUniverse = em.keyUniverse;
173
vals = em.vals.clone();
174
size = em.size;
175
} else {
176
if (m.isEmpty())
177
throw new IllegalArgumentException("Specified map is empty");
178
keyType = m.keySet().iterator().next().getDeclaringClass();
179
keyUniverse = getKeyUniverse(keyType);
180
vals = new Object[keyUniverse.length];
181
putAll(m);
182
}
183
}
184
185
// Query Operations
186
187
/**
188
* Returns the number of key-value mappings in this map.
189
*
190
* @return the number of key-value mappings in this map
191
*/
192
public int size() {
193
return size;
194
}
195
196
/**
197
* Returns <tt>true</tt> if this map maps one or more keys to the
198
* specified value.
199
*
200
* @param value the value whose presence in this map is to be tested
201
* @return <tt>true</tt> if this map maps one or more keys to this value
202
*/
203
public boolean containsValue(Object value) {
204
value = maskNull(value);
205
206
for (Object val : vals)
207
if (value.equals(val))
208
return true;
209
210
return false;
211
}
212
213
/**
214
* Returns <tt>true</tt> if this map contains a mapping for the specified
215
* key.
216
*
217
* @param key the key whose presence in this map is to be tested
218
* @return <tt>true</tt> if this map contains a mapping for the specified
219
* key
220
*/
221
public boolean containsKey(Object key) {
222
return isValidKey(key) && vals[((Enum<?>)key).ordinal()] != null;
223
}
224
225
private boolean containsMapping(Object key, Object value) {
226
return isValidKey(key) &&
227
maskNull(value).equals(vals[((Enum<?>)key).ordinal()]);
228
}
229
230
/**
231
* Returns the value to which the specified key is mapped,
232
* or {@code null} if this map contains no mapping for the key.
233
*
234
* <p>More formally, if this map contains a mapping from a key
235
* {@code k} to a value {@code v} such that {@code (key == k)},
236
* then this method returns {@code v}; otherwise it returns
237
* {@code null}. (There can be at most one such mapping.)
238
*
239
* <p>A return value of {@code null} does not <i>necessarily</i>
240
* indicate that the map contains no mapping for the key; it's also
241
* possible that the map explicitly maps the key to {@code null}.
242
* The {@link #containsKey containsKey} operation may be used to
243
* distinguish these two cases.
244
*/
245
public V get(Object key) {
246
return (isValidKey(key) ?
247
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
248
}
249
250
// Modification Operations
251
252
/**
253
* Associates the specified value with the specified key in this map.
254
* If the map previously contained a mapping for this key, the old
255
* value is replaced.
256
*
257
* @param key the key with which the specified value is to be associated
258
* @param value the value to be associated with the specified key
259
*
260
* @return the previous value associated with specified key, or
261
* <tt>null</tt> if there was no mapping for key. (A <tt>null</tt>
262
* return can also indicate that the map previously associated
263
* <tt>null</tt> with the specified key.)
264
* @throws NullPointerException if the specified key is null
265
*/
266
public V put(K key, V value) {
267
typeCheck(key);
268
269
int index = key.ordinal();
270
Object oldValue = vals[index];
271
vals[index] = maskNull(value);
272
if (oldValue == null)
273
size++;
274
return unmaskNull(oldValue);
275
}
276
277
/**
278
* Removes the mapping for this key from this map if present.
279
*
280
* @param key the key whose mapping is to be removed from the map
281
* @return the previous value associated with specified key, or
282
* <tt>null</tt> if there was no entry for key. (A <tt>null</tt>
283
* return can also indicate that the map previously associated
284
* <tt>null</tt> with the specified key.)
285
*/
286
public V remove(Object key) {
287
if (!isValidKey(key))
288
return null;
289
int index = ((Enum<?>)key).ordinal();
290
Object oldValue = vals[index];
291
vals[index] = null;
292
if (oldValue != null)
293
size--;
294
return unmaskNull(oldValue);
295
}
296
297
private boolean removeMapping(Object key, Object value) {
298
if (!isValidKey(key))
299
return false;
300
int index = ((Enum<?>)key).ordinal();
301
if (maskNull(value).equals(vals[index])) {
302
vals[index] = null;
303
size--;
304
return true;
305
}
306
return false;
307
}
308
309
/**
310
* Returns true if key is of the proper type to be a key in this
311
* enum map.
312
*/
313
private boolean isValidKey(Object key) {
314
if (key == null)
315
return false;
316
317
// Cheaper than instanceof Enum followed by getDeclaringClass
318
Class<?> keyClass = key.getClass();
319
return keyClass == keyType || keyClass.getSuperclass() == keyType;
320
}
321
322
// Bulk Operations
323
324
/**
325
* Copies all of the mappings from the specified map to this map.
326
* These mappings will replace any mappings that this map had for
327
* any of the keys currently in the specified map.
328
*
329
* @param m the mappings to be stored in this map
330
* @throws NullPointerException the specified map is null, or if
331
* one or more keys in the specified map are null
332
*/
333
public void putAll(Map<? extends K, ? extends V> m) {
334
if (m instanceof EnumMap) {
335
EnumMap<?, ?> em = (EnumMap<?, ?>)m;
336
if (em.keyType != keyType) {
337
if (em.isEmpty())
338
return;
339
throw new ClassCastException(em.keyType + " != " + keyType);
340
}
341
342
for (int i = 0; i < keyUniverse.length; i++) {
343
Object emValue = em.vals[i];
344
if (emValue != null) {
345
if (vals[i] == null)
346
size++;
347
vals[i] = emValue;
348
}
349
}
350
} else {
351
super.putAll(m);
352
}
353
}
354
355
/**
356
* Removes all mappings from this map.
357
*/
358
public void clear() {
359
Arrays.fill(vals, null);
360
size = 0;
361
}
362
363
// Views
364
365
/**
366
* This field is initialized to contain an instance of the entry set
367
* view the first time this view is requested. The view is stateless,
368
* so there's no reason to create more than one.
369
*/
370
private transient Set<Map.Entry<K,V>> entrySet;
371
372
/**
373
* Returns a {@link Set} view of the keys contained in this map.
374
* The returned set obeys the general contract outlined in
375
* {@link Map#keySet()}. The set's iterator will return the keys
376
* in their natural order (the order in which the enum constants
377
* are declared).
378
*
379
* @return a set view of the keys contained in this enum map
380
*/
381
public Set<K> keySet() {
382
Set<K> ks = keySet;
383
if (ks == null) {
384
ks = new KeySet();
385
keySet = ks;
386
}
387
return ks;
388
}
389
390
private class KeySet extends AbstractSet<K> {
391
public Iterator<K> iterator() {
392
return new KeyIterator();
393
}
394
public int size() {
395
return size;
396
}
397
public boolean contains(Object o) {
398
return containsKey(o);
399
}
400
public boolean remove(Object o) {
401
int oldSize = size;
402
EnumMap.this.remove(o);
403
return size != oldSize;
404
}
405
public void clear() {
406
EnumMap.this.clear();
407
}
408
}
409
410
/**
411
* Returns a {@link Collection} view of the values contained in this map.
412
* The returned collection obeys the general contract outlined in
413
* {@link Map#values()}. The collection's iterator will return the
414
* values in the order their corresponding keys appear in map,
415
* which is their natural order (the order in which the enum constants
416
* are declared).
417
*
418
* @return a collection view of the values contained in this map
419
*/
420
public Collection<V> values() {
421
Collection<V> vs = values;
422
if (vs == null) {
423
vs = new Values();
424
values = vs;
425
}
426
return vs;
427
}
428
429
private class Values extends AbstractCollection<V> {
430
public Iterator<V> iterator() {
431
return new ValueIterator();
432
}
433
public int size() {
434
return size;
435
}
436
public boolean contains(Object o) {
437
return containsValue(o);
438
}
439
public boolean remove(Object o) {
440
o = maskNull(o);
441
442
for (int i = 0; i < vals.length; i++) {
443
if (o.equals(vals[i])) {
444
vals[i] = null;
445
size--;
446
return true;
447
}
448
}
449
return false;
450
}
451
public void clear() {
452
EnumMap.this.clear();
453
}
454
}
455
456
/**
457
* Returns a {@link Set} view of the mappings contained in this map.
458
* The returned set obeys the general contract outlined in
459
* {@link Map#keySet()}. The set's iterator will return the
460
* mappings in the order their keys appear in map, which is their
461
* natural order (the order in which the enum constants are declared).
462
*
463
* @return a set view of the mappings contained in this enum map
464
*/
465
public Set<Map.Entry<K,V>> entrySet() {
466
Set<Map.Entry<K,V>> es = entrySet;
467
if (es != null)
468
return es;
469
else
470
return entrySet = new EntrySet();
471
}
472
473
private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
474
public Iterator<Map.Entry<K,V>> iterator() {
475
return new EntryIterator();
476
}
477
478
public boolean contains(Object o) {
479
if (!(o instanceof Map.Entry))
480
return false;
481
Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
482
return containsMapping(entry.getKey(), entry.getValue());
483
}
484
public boolean remove(Object o) {
485
if (!(o instanceof Map.Entry))
486
return false;
487
Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
488
return removeMapping(entry.getKey(), entry.getValue());
489
}
490
public int size() {
491
return size;
492
}
493
public void clear() {
494
EnumMap.this.clear();
495
}
496
public Object[] toArray() {
497
return fillEntryArray(new Object[size]);
498
}
499
@SuppressWarnings("unchecked")
500
public <T> T[] toArray(T[] a) {
501
int size = size();
502
if (a.length < size)
503
a = (T[])java.lang.reflect.Array
504
.newInstance(a.getClass().getComponentType(), size);
505
if (a.length > size)
506
a[size] = null;
507
return (T[]) fillEntryArray(a);
508
}
509
private Object[] fillEntryArray(Object[] a) {
510
int j = 0;
511
for (int i = 0; i < vals.length; i++)
512
if (vals[i] != null)
513
a[j++] = new AbstractMap.SimpleEntry<>(
514
keyUniverse[i], unmaskNull(vals[i]));
515
return a;
516
}
517
}
518
519
private abstract class EnumMapIterator<T> implements Iterator<T> {
520
// Lower bound on index of next element to return
521
int index = 0;
522
523
// Index of last returned element, or -1 if none
524
int lastReturnedIndex = -1;
525
526
public boolean hasNext() {
527
while (index < vals.length && vals[index] == null)
528
index++;
529
return index != vals.length;
530
}
531
532
public void remove() {
533
checkLastReturnedIndex();
534
535
if (vals[lastReturnedIndex] != null) {
536
vals[lastReturnedIndex] = null;
537
size--;
538
}
539
lastReturnedIndex = -1;
540
}
541
542
private void checkLastReturnedIndex() {
543
if (lastReturnedIndex < 0)
544
throw new IllegalStateException();
545
}
546
}
547
548
private class KeyIterator extends EnumMapIterator<K> {
549
public K next() {
550
if (!hasNext())
551
throw new NoSuchElementException();
552
lastReturnedIndex = index++;
553
return keyUniverse[lastReturnedIndex];
554
}
555
}
556
557
private class ValueIterator extends EnumMapIterator<V> {
558
public V next() {
559
if (!hasNext())
560
throw new NoSuchElementException();
561
lastReturnedIndex = index++;
562
return unmaskNull(vals[lastReturnedIndex]);
563
}
564
}
565
566
private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
567
private Entry lastReturnedEntry;
568
569
public Map.Entry<K,V> next() {
570
if (!hasNext())
571
throw new NoSuchElementException();
572
lastReturnedEntry = new Entry(index++);
573
return lastReturnedEntry;
574
}
575
576
public void remove() {
577
lastReturnedIndex =
578
((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
579
super.remove();
580
lastReturnedEntry.index = lastReturnedIndex;
581
lastReturnedEntry = null;
582
}
583
584
private class Entry implements Map.Entry<K,V> {
585
private int index;
586
587
private Entry(int index) {
588
this.index = index;
589
}
590
591
public K getKey() {
592
checkIndexForEntryUse();
593
return keyUniverse[index];
594
}
595
596
public V getValue() {
597
checkIndexForEntryUse();
598
return unmaskNull(vals[index]);
599
}
600
601
public V setValue(V value) {
602
checkIndexForEntryUse();
603
V oldValue = unmaskNull(vals[index]);
604
vals[index] = maskNull(value);
605
return oldValue;
606
}
607
608
public boolean equals(Object o) {
609
if (index < 0)
610
return o == this;
611
612
if (!(o instanceof Map.Entry))
613
return false;
614
615
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
616
V ourValue = unmaskNull(vals[index]);
617
Object hisValue = e.getValue();
618
return (e.getKey() == keyUniverse[index] &&
619
(ourValue == hisValue ||
620
(ourValue != null && ourValue.equals(hisValue))));
621
}
622
623
public int hashCode() {
624
if (index < 0)
625
return super.hashCode();
626
627
return entryHashCode(index);
628
}
629
630
public String toString() {
631
if (index < 0)
632
return super.toString();
633
634
return keyUniverse[index] + "="
635
+ unmaskNull(vals[index]);
636
}
637
638
private void checkIndexForEntryUse() {
639
if (index < 0)
640
throw new IllegalStateException("Entry was removed");
641
}
642
}
643
}
644
645
// Comparison and hashing
646
647
/**
648
* Compares the specified object with this map for equality. Returns
649
* <tt>true</tt> if the given object is also a map and the two maps
650
* represent the same mappings, as specified in the {@link
651
* Map#equals(Object)} contract.
652
*
653
* @param o the object to be compared for equality with this map
654
* @return <tt>true</tt> if the specified object is equal to this map
655
*/
656
public boolean equals(Object o) {
657
if (this == o)
658
return true;
659
if (o instanceof EnumMap)
660
return equals((EnumMap<?,?>)o);
661
if (!(o instanceof Map))
662
return false;
663
664
Map<?,?> m = (Map<?,?>)o;
665
if (size != m.size())
666
return false;
667
668
for (int i = 0; i < keyUniverse.length; i++) {
669
if (null != vals[i]) {
670
K key = keyUniverse[i];
671
V value = unmaskNull(vals[i]);
672
if (null == value) {
673
if (!((null == m.get(key)) && m.containsKey(key)))
674
return false;
675
} else {
676
if (!value.equals(m.get(key)))
677
return false;
678
}
679
}
680
}
681
682
return true;
683
}
684
685
private boolean equals(EnumMap<?,?> em) {
686
if (em.keyType != keyType)
687
return size == 0 && em.size == 0;
688
689
// Key types match, compare each value
690
for (int i = 0; i < keyUniverse.length; i++) {
691
Object ourValue = vals[i];
692
Object hisValue = em.vals[i];
693
if (hisValue != ourValue &&
694
(hisValue == null || !hisValue.equals(ourValue)))
695
return false;
696
}
697
return true;
698
}
699
700
/**
701
* Returns the hash code value for this map. The hash code of a map is
702
* defined to be the sum of the hash codes of each entry in the map.
703
*/
704
public int hashCode() {
705
int h = 0;
706
707
for (int i = 0; i < keyUniverse.length; i++) {
708
if (null != vals[i]) {
709
h += entryHashCode(i);
710
}
711
}
712
713
return h;
714
}
715
716
private int entryHashCode(int index) {
717
return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
718
}
719
720
/**
721
* Returns a shallow copy of this enum map. (The values themselves
722
* are not cloned.
723
*
724
* @return a shallow copy of this enum map
725
*/
726
@SuppressWarnings("unchecked")
727
public EnumMap<K, V> clone() {
728
EnumMap<K, V> result = null;
729
try {
730
result = (EnumMap<K, V>) super.clone();
731
} catch(CloneNotSupportedException e) {
732
throw new AssertionError();
733
}
734
result.vals = result.vals.clone();
735
result.entrySet = null;
736
return result;
737
}
738
739
/**
740
* Throws an exception if e is not of the correct type for this enum set.
741
*/
742
private void typeCheck(K key) {
743
Class<?> keyClass = key.getClass();
744
if (keyClass != keyType && keyClass.getSuperclass() != keyType)
745
throw new ClassCastException(keyClass + " != " + keyType);
746
}
747
748
/**
749
* Returns all of the values comprising K.
750
* The result is uncloned, cached, and shared by all callers.
751
*/
752
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
753
return SharedSecrets.getJavaLangAccess()
754
.getEnumConstantsShared(keyType);
755
}
756
757
private static final long serialVersionUID = 458661240069192865L;
758
759
/**
760
* Save the state of the <tt>EnumMap</tt> instance to a stream (i.e.,
761
* serialize it).
762
*
763
* @serialData The <i>size</i> of the enum map (the number of key-value
764
* mappings) is emitted (int), followed by the key (Object)
765
* and value (Object) for each key-value mapping represented
766
* by the enum map.
767
*/
768
private void writeObject(java.io.ObjectOutputStream s)
769
throws java.io.IOException
770
{
771
// Write out the key type and any hidden stuff
772
s.defaultWriteObject();
773
774
// Write out size (number of Mappings)
775
s.writeInt(size);
776
777
// Write out keys and values (alternating)
778
int entriesToBeWritten = size;
779
for (int i = 0; entriesToBeWritten > 0; i++) {
780
if (null != vals[i]) {
781
s.writeObject(keyUniverse[i]);
782
s.writeObject(unmaskNull(vals[i]));
783
entriesToBeWritten--;
784
}
785
}
786
}
787
788
/**
789
* Reconstitute the <tt>EnumMap</tt> instance from a stream (i.e.,
790
* deserialize it).
791
*/
792
@SuppressWarnings("unchecked")
793
private void readObject(java.io.ObjectInputStream s)
794
throws java.io.IOException, ClassNotFoundException
795
{
796
// Read in the key type and any hidden stuff
797
s.defaultReadObject();
798
799
keyUniverse = getKeyUniverse(keyType);
800
vals = new Object[keyUniverse.length];
801
802
// Read in size (number of Mappings)
803
int size = s.readInt();
804
805
// Read the keys and values, and put the mappings in the HashMap
806
for (int i = 0; i < size; i++) {
807
K key = (K) s.readObject();
808
V value = (V) s.readObject();
809
put(key, value);
810
}
811
}
812
}
813
814