OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [util/] [WeakHashMap.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* WeakHashMap -- a hashtable that keeps only weak references
2
   to its keys, allowing the virtual machine to reclaim them
3
   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package java.util;
41
 
42
import java.lang.ref.ReferenceQueue;
43
import java.lang.ref.WeakReference;
44
 
45
/**
46
 * A weak hash map has only weak references to the key. This means that it
47
 * allows the key to be garbage collected if it is not used otherwise. If
48
 * this happens, the entry will eventually disappear from the map,
49
 * asynchronously.
50
 *
51
 * <p>A weak hash map makes most sense when the keys doesn't override the
52
 * <code>equals</code> method: If there is no other reference to the
53
 * key nobody can ever look up the key in this table and so the entry
54
 * can be removed.  This table also works when the <code>equals</code>
55
 * method is overloaded, such as String keys, but you should be prepared
56
 * to deal with some entries disappearing spontaneously.
57
 *
58
 * <p>Other strange behaviors to be aware of: The size of this map may
59
 * spontaneously shrink (even if you use a synchronized map and synchronize
60
 * it); it behaves as if another thread removes entries from this table
61
 * without synchronization.  The entry set returned by <code>entrySet</code>
62
 * has similar phenomenons: The size may spontaneously shrink, or an
63
 * entry, that was in the set before, suddenly disappears.
64
 *
65
 * <p>A weak hash map is not meant for caches; use a normal map, with
66
 * soft references as values instead, or try {@link LinkedHashMap}.
67
 *
68
 * <p>The weak hash map supports null values and null keys.  The null key
69
 * is never deleted from the map (except explictly of course). The
70
 * performance of the methods are similar to that of a hash map.
71
 *
72
 * <p>The value objects are strongly referenced by this table.  So if a
73
 * value object maintains a strong reference to the key (either direct
74
 * or indirect) the key will never be removed from this map.  According
75
 * to Sun, this problem may be fixed in a future release.  It is not
76
 * possible to do it with the jdk 1.2 reference model, though.
77
 *
78
 * @author Jochen Hoenicke
79
 * @author Eric Blake (ebb9@email.byu.edu)
80
 *
81
 * @see HashMap
82
 * @see WeakReference
83
 * @see LinkedHashMap
84
 * @since 1.2
85
 * @status updated to 1.4
86
 */
87
public class WeakHashMap extends AbstractMap implements Map
88
{
89
  // WARNING: WeakHashMap is a CORE class in the bootstrap cycle. See the
90
  // comments in vm/reference/java/lang/Runtime for implications of this fact.
91
 
92
  /**
93
   * The default capacity for an instance of HashMap.
94
   * Sun's documentation mildly suggests that this (11) is the correct
95
   * value.
96
   */
97
  private static final int DEFAULT_CAPACITY = 11;
98
 
99
  /**
100
   * The default load factor of a HashMap.
101
   */
102
  private static final float DEFAULT_LOAD_FACTOR = 0.75F;
103
 
104
  /**
105
   * This is used instead of the key value <i>null</i>.  It is needed
106
   * to distinguish between an null key and a removed key.
107
   */
108
  // Package visible for use by nested classes.
109
  static final Object NULL_KEY = new Object()
110
  {
111
    /**
112
     * Sets the hashCode to 0, since that's what null would map to.
113
     * @return the hash code 0
114
     */
115
    public int hashCode()
116
    {
117
      return 0;
118
    }
119
 
120
    /**
121
     * Compares this key to the given object. Normally, an object should
122
     * NEVER compare equal to null, but since we don't publicize NULL_VALUE,
123
     * it saves bytecode to do so here.
124
     * @return true iff o is this or null
125
     */
126
    public boolean equals(Object o)
127
    {
128
      return null == o || this == o;
129
    }
130
  };
131
 
132
  /**
133
   * The reference queue where our buckets (which are WeakReferences) are
134
   * registered to.
135
   */
136
  private final ReferenceQueue queue;
137
 
138
  /**
139
   * The number of entries in this hash map.
140
   */
141
  // Package visible for use by nested classes.
142
  int size;
143
 
144
  /**
145
   * The load factor of this WeakHashMap.  This is the maximum ratio of
146
   * size versus number of buckets.  If size grows the number of buckets
147
   * must grow, too.
148
   */
149
  private float loadFactor;
150
 
151
  /**
152
   * The rounded product of the capacity (i.e. number of buckets) and
153
   * the load factor. When the number of elements exceeds the
154
   * threshold, the HashMap calls <code>rehash()</code>.
155
   */
156
  private int threshold;
157
 
158
  /**
159
   * The number of structural modifications.  This is used by
160
   * iterators, to see if they should fail.  This doesn't count
161
   * the silent key removals, when a weak reference is cleared
162
   * by the garbage collection.  Instead the iterators must make
163
   * sure to have strong references to the entries they rely on.
164
   */
165
  // Package visible for use by nested classes.
166
  int modCount;
167
 
168
  /**
169
   * The entry set.  There is only one instance per hashmap, namely
170
   * theEntrySet.  Note that the entry set may silently shrink, just
171
   * like the WeakHashMap.
172
   */
173
  private final class WeakEntrySet extends AbstractSet
174
  {
175
    /**
176
     * Non-private constructor to reduce bytecode emitted.
177
     */
178
    WeakEntrySet()
179
    {
180
    }
181
 
182
    /**
183
     * Returns the size of this set.
184
     *
185
     * @return the set size
186
     */
187
    public int size()
188
    {
189
      return size;
190
    }
191
 
192
    /**
193
     * Returns an iterator for all entries.
194
     *
195
     * @return an Entry iterator
196
     */
197
    public Iterator iterator()
198
    {
199
      return new Iterator()
200
      {
201
        /**
202
         * The entry that was returned by the last
203
         * <code>next()</code> call.  This is also the entry whose
204
         * bucket should be removed by the <code>remove</code> call. <br>
205
         *
206
         * It is null, if the <code>next</code> method wasn't
207
         * called yet, or if the entry was already removed.  <br>
208
         *
209
         * Remembering this entry here will also prevent it from
210
         * being removed under us, since the entry strongly refers
211
         * to the key.
212
         */
213
        WeakBucket.WeakEntry lastEntry;
214
 
215
        /**
216
         * The entry that will be returned by the next
217
         * <code>next()</code> call.  It is <code>null</code> if there
218
         * is no further entry. <br>
219
         *
220
         * Remembering this entry here will also prevent it from
221
         * being removed under us, since the entry strongly refers
222
         * to the key.
223
         */
224
        WeakBucket.WeakEntry nextEntry = findNext(null);
225
 
226
        /**
227
         * The known number of modification to the list, if it differs
228
         * from the real number, we throw an exception.
229
         */
230
        int knownMod = modCount;
231
 
232
        /**
233
         * Check the known number of modification to the number of
234
         * modifications of the table.  If it differs from the real
235
         * number, we throw an exception.
236
         * @throws ConcurrentModificationException if the number
237
         *         of modifications doesn't match.
238
         */
239
        private void checkMod()
240
        {
241
          // This method will get inlined.
242
          cleanQueue();
243
          if (knownMod != modCount)
244
            throw new ConcurrentModificationException(knownMod + " != "
245
                                                      + modCount);
246
        }
247
 
248
        /**
249
         * Get a strong reference to the next entry after
250
         * lastBucket.
251
         * @param lastEntry the previous bucket, or null if we should
252
         * get the first entry.
253
         * @return the next entry.
254
         */
255
        private WeakBucket.WeakEntry findNext(WeakBucket.WeakEntry lastEntry)
256
        {
257
          int slot;
258
          WeakBucket nextBucket;
259
          if (lastEntry != null)
260
            {
261
              nextBucket = lastEntry.getBucket().next;
262
              slot = lastEntry.getBucket().slot;
263
            }
264
          else
265
            {
266
              nextBucket = buckets[0];
267
              slot = 0;
268
            }
269
 
270
          while (true)
271
            {
272
              while (nextBucket != null)
273
                {
274
                  WeakBucket.WeakEntry entry = nextBucket.getEntry();
275
                  if (entry != null)
276
                    // This is the next entry.
277
                    return entry;
278
 
279
                  // Entry was cleared, try next.
280
                  nextBucket = nextBucket.next;
281
                }
282
 
283
              slot++;
284
              if (slot == buckets.length)
285
                // No more buckets, we are through.
286
                return null;
287
 
288
              nextBucket = buckets[slot];
289
            }
290
        }
291
 
292
        /**
293
         * Checks if there are more entries.
294
         * @return true, iff there are more elements.
295
         */
296
        public boolean hasNext()
297
        {
298
          return nextEntry != null;
299
        }
300
 
301
        /**
302
         * Returns the next entry.
303
         * @return the next entry.
304
         * @throws ConcurrentModificationException if the hash map was
305
         *         modified.
306
         * @throws NoSuchElementException if there is no entry.
307
         */
308
        public Object next()
309
        {
310
          checkMod();
311
          if (nextEntry == null)
312
            throw new NoSuchElementException();
313
          lastEntry = nextEntry;
314
          nextEntry = findNext(lastEntry);
315
          return lastEntry;
316
        }
317
 
318
        /**
319
         * Removes the last returned entry from this set.  This will
320
         * also remove the bucket of the underlying weak hash map.
321
         * @throws ConcurrentModificationException if the hash map was
322
         *         modified.
323
         * @throws IllegalStateException if <code>next()</code> was
324
         *         never called or the element was already removed.
325
         */
326
        public void remove()
327
        {
328
          checkMod();
329
          if (lastEntry == null)
330
            throw new IllegalStateException();
331
          modCount++;
332
          internalRemove(lastEntry.getBucket());
333
          lastEntry = null;
334
          knownMod++;
335
        }
336
      };
337
    }
338
  }
339
 
340
  /**
341
   * A bucket is a weak reference to the key, that contains a strong
342
   * reference to the value, a pointer to the next bucket and its slot
343
   * number. <br>
344
   *
345
   * It would be cleaner to have a WeakReference as field, instead of
346
   * extending it, but if a weak reference gets cleared, we only get
347
   * the weak reference (by queue.poll) and wouldn't know where to
348
   * look for this reference in the hashtable, to remove that entry.
349
   *
350
   * @author Jochen Hoenicke
351
   */
352
  private static class WeakBucket extends WeakReference
353
  {
354
    /**
355
     * The value of this entry.  The key is stored in the weak
356
     * reference that we extend.
357
     */
358
    Object value;
359
 
360
    /**
361
     * The next bucket describing another entry that uses the same
362
     * slot.
363
     */
364
    WeakBucket next;
365
 
366
    /**
367
     * The slot of this entry. This should be
368
     * <code>Math.abs(key.hashCode() % buckets.length)</code>.
369
     *
370
     * But since the key may be silently removed we have to remember
371
     * the slot number.
372
     *
373
     * If this bucket was removed the slot is -1.  This marker will
374
     * prevent the bucket from being removed twice.
375
     */
376
    int slot;
377
 
378
    /**
379
     * Creates a new bucket for the given key/value pair and the specified
380
     * slot.
381
     * @param key the key
382
     * @param queue the queue the weak reference belongs to
383
     * @param value the value
384
     * @param slot the slot.  This must match the slot where this bucket
385
     *        will be enqueued.
386
     */
387
    public WeakBucket(Object key, ReferenceQueue queue, Object value,
388
                      int slot)
389
    {
390
      super(key, queue);
391
      this.value = value;
392
      this.slot = slot;
393
    }
394
 
395
    /**
396
     * This class gives the <code>Entry</code> representation of the
397
     * current bucket.  It also keeps a strong reference to the
398
     * key; bad things may happen otherwise.
399
     */
400
    class WeakEntry implements Map.Entry
401
    {
402
      /**
403
       * The strong ref to the key.
404
       */
405
      Object key;
406
 
407
      /**
408
       * Creates a new entry for the key.
409
       * @param key the key
410
       */
411
      public WeakEntry(Object key)
412
      {
413
        this.key = key;
414
      }
415
 
416
      /**
417
       * Returns the underlying bucket.
418
       * @return the owning bucket
419
       */
420
      public WeakBucket getBucket()
421
      {
422
        return WeakBucket.this;
423
      }
424
 
425
      /**
426
       * Returns the key.
427
       * @return the key
428
       */
429
      public Object getKey()
430
      {
431
        return key == NULL_KEY ? null : key;
432
      }
433
 
434
      /**
435
       * Returns the value.
436
       * @return the value
437
       */
438
      public Object getValue()
439
      {
440
        return value;
441
      }
442
 
443
      /**
444
       * This changes the value.  This change takes place in
445
       * the underlying hash map.
446
       * @param newVal the new value
447
       * @return the old value
448
       */
449
      public Object setValue(Object newVal)
450
      {
451
        Object oldVal = value;
452
        value = newVal;
453
        return oldVal;
454
      }
455
 
456
      /**
457
       * The hashCode as specified in the Entry interface.
458
       * @return the hash code
459
       */
460
      public int hashCode()
461
      {
462
        return key.hashCode() ^ WeakHashMap.hashCode(value);
463
      }
464
 
465
      /**
466
       * The equals method as specified in the Entry interface.
467
       * @param o the object to compare to
468
       * @return true iff o represents the same key/value pair
469
       */
470
      public boolean equals(Object o)
471
      {
472
        if (o instanceof Map.Entry)
473
          {
474
            Map.Entry e = (Map.Entry) o;
475
            return WeakHashMap.equals(getKey(), e.getKey())
476
              && WeakHashMap.equals(value, e.getValue());
477
          }
478
        return false;
479
      }
480
 
481
      public String toString()
482
      {
483
        return getKey() + "=" + value;
484
      }
485
    }
486
 
487
    /**
488
     * This returns the entry stored in this bucket, or null, if the
489
     * bucket got cleared in the mean time.
490
     * @return the Entry for this bucket, if it exists
491
     */
492
    WeakEntry getEntry()
493
    {
494
      final Object key = this.get();
495
      if (key == null)
496
        return null;
497
      return new WeakEntry(key);
498
    }
499
  }
500
 
501
  /**
502
   * The entry set returned by <code>entrySet()</code>.
503
   */
504
  private final WeakEntrySet theEntrySet;
505
 
506
  /**
507
   * The hash buckets.  These are linked lists. Package visible for use in
508
   * nested classes.
509
   */
510
  WeakBucket[] buckets;
511
 
512
  /**
513
   * Creates a new weak hash map with default load factor and default
514
   * capacity.
515
   */
516
  public WeakHashMap()
517
  {
518
    this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
519
  }
520
 
521
  /**
522
   * Creates a new weak hash map with default load factor and the given
523
   * capacity.
524
   * @param initialCapacity the initial capacity
525
   * @throws IllegalArgumentException if initialCapacity is negative
526
   */
527
  public WeakHashMap(int initialCapacity)
528
  {
529
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
530
  }
531
 
532
  /**
533
   * Creates a new weak hash map with the given initial capacity and
534
   * load factor.
535
   * @param initialCapacity the initial capacity.
536
   * @param loadFactor the load factor (see class description of HashMap).
537
   * @throws IllegalArgumentException if initialCapacity is negative, or
538
   *         loadFactor is non-positive
539
   */
540
  public WeakHashMap(int initialCapacity, float loadFactor)
541
  {
542
    // Check loadFactor for NaN as well.
543
    if (initialCapacity < 0 || ! (loadFactor > 0))
544
      throw new IllegalArgumentException();
545
    if (initialCapacity == 0)
546
      initialCapacity = 1;
547
    this.loadFactor = loadFactor;
548
    threshold = (int) (initialCapacity * loadFactor);
549
    theEntrySet = new WeakEntrySet();
550
    queue = new ReferenceQueue();
551
    buckets = new WeakBucket[initialCapacity];
552
  }
553
 
554
  /**
555
   * Construct a new WeakHashMap with the same mappings as the given map.
556
   * The WeakHashMap has a default load factor of 0.75.
557
   *
558
   * @param m the map to copy
559
   * @throws NullPointerException if m is null
560
   * @since 1.3
561
   */
562
  public WeakHashMap(Map m)
563
  {
564
    this(m.size(), DEFAULT_LOAD_FACTOR);
565
    putAll(m);
566
  }
567
 
568
  /**
569
   * Simply hashes a non-null Object to its array index.
570
   * @param key the key to hash
571
   * @return its slot number
572
   */
573
  private int hash(Object key)
574
  {
575
    return Math.abs(key.hashCode() % buckets.length);
576
  }
577
 
578
  /**
579
   * Cleans the reference queue.  This will poll all references (which
580
   * are WeakBuckets) from the queue and remove them from this map.
581
   * This will not change modCount, even if it modifies the map.  The
582
   * iterators have to make sure that nothing bad happens.  <br>
583
   *
584
   * Currently the iterator maintains a strong reference to the key, so
585
   * that is no problem.
586
   */
587
  // Package visible for use by nested classes.
588
  void cleanQueue()
589
  {
590
    Object bucket = queue.poll();
591
    while (bucket != null)
592
      {
593
        internalRemove((WeakBucket) bucket);
594
        bucket = queue.poll();
595
      }
596
  }
597
 
598
  /**
599
   * Rehashes this hashtable.  This will be called by the
600
   * <code>add()</code> method if the size grows beyond the threshold.
601
   * It will grow the bucket size at least by factor two and allocates
602
   * new buckets.
603
   */
604
  private void rehash()
605
  {
606
    WeakBucket[] oldBuckets = buckets;
607
    int newsize = buckets.length * 2 + 1; // XXX should be prime.
608
    threshold = (int) (newsize * loadFactor);
609
    buckets = new WeakBucket[newsize];
610
 
611
    // Now we have to insert the buckets again.
612
    for (int i = 0; i < oldBuckets.length; i++)
613
      {
614
        WeakBucket bucket = oldBuckets[i];
615
        WeakBucket nextBucket;
616
        while (bucket != null)
617
          {
618
            nextBucket = bucket.next;
619
 
620
            Object key = bucket.get();
621
            if (key == null)
622
              {
623
                // This bucket should be removed; it is probably
624
                // already on the reference queue.  We don't insert it
625
                // at all, and mark it as cleared.
626
                bucket.slot = -1;
627
                size--;
628
              }
629
            else
630
              {
631
                // Add this bucket to its new slot.
632
                int slot = hash(key);
633
                bucket.slot = slot;
634
                bucket.next = buckets[slot];
635
                buckets[slot] = bucket;
636
              }
637
            bucket = nextBucket;
638
          }
639
      }
640
  }
641
 
642
  /**
643
   * Finds the entry corresponding to key.  Since it returns an Entry
644
   * it will also prevent the key from being removed under us.
645
   * @param key the key, may be null
646
   * @return The WeakBucket.WeakEntry or null, if the key wasn't found.
647
   */
648
  private WeakBucket.WeakEntry internalGet(Object key)
649
  {
650
    if (key == null)
651
      key = NULL_KEY;
652
    int slot = hash(key);
653
    WeakBucket bucket = buckets[slot];
654
    while (bucket != null)
655
      {
656
        WeakBucket.WeakEntry entry = bucket.getEntry();
657
        if (entry != null && equals(key, entry.key))
658
          return entry;
659
 
660
        bucket = bucket.next;
661
      }
662
    return null;
663
  }
664
 
665
  /**
666
   * Adds a new key/value pair to the hash map.
667
   * @param key the key. This mustn't exists in the map. It may be null.
668
   * @param value the value.
669
   */
670
  private void internalAdd(Object key, Object value)
671
  {
672
    if (key == null)
673
      key = NULL_KEY;
674
    int slot = hash(key);
675
    WeakBucket bucket = new WeakBucket(key, queue, value, slot);
676
    bucket.next = buckets[slot];
677
    buckets[slot] = bucket;
678
    size++;
679
  }
680
 
681
  /**
682
   * Removes a bucket from this hash map, if it wasn't removed before
683
   * (e.g. one time through rehashing and one time through reference queue).
684
   * Package visible for use in nested classes.
685
   *
686
   * @param bucket the bucket to remove.
687
   */
688
  void internalRemove(WeakBucket bucket)
689
  {
690
    int slot = bucket.slot;
691
    if (slot == -1)
692
      // This bucket was already removed.
693
      return;
694
 
695
    // Mark the bucket as removed.  This is necessary, since the
696
    // bucket may be enqueued later by the garbage collection, and
697
    // internalRemove will be called a second time.
698
    bucket.slot = -1;
699
 
700
    WeakBucket prev = null;
701
    WeakBucket next = buckets[slot];
702
    while (next != bucket)
703
      {
704
         if (next == null) throw new InternalError("WeakHashMap in incosistent state");
705
         prev = next;
706
         next = prev.next;
707
      }
708
    if (prev == null)
709
      buckets[slot] = bucket.next;
710
    else
711
      prev.next = bucket.next;
712
 
713
    size--;
714
  }
715
 
716
  /**
717
   * Returns the size of this hash map.  Note that the size() may shrink
718
   * spontaneously, if the some of the keys were only weakly reachable.
719
   * @return the number of entries in this hash map.
720
   */
721
  public int size()
722
  {
723
    cleanQueue();
724
    return size;
725
  }
726
 
727
  /**
728
   * Tells if the map is empty.  Note that the result may change
729
   * spontanously, if all of the keys were only weakly reachable.
730
   * @return true, iff the map is empty.
731
   */
732
  public boolean isEmpty()
733
  {
734
    cleanQueue();
735
    return size == 0;
736
  }
737
 
738
  /**
739
   * Tells if the map contains the given key.  Note that the result
740
   * may change spontanously, if the key was only weakly
741
   * reachable.
742
   * @param key the key to look for
743
   * @return true, iff the map contains an entry for the given key.
744
   */
745
  public boolean containsKey(Object key)
746
  {
747
    cleanQueue();
748
    return internalGet(key) != null;
749
  }
750
 
751
  /**
752
   * Gets the value the key is mapped to.
753
   * @return the value the key was mapped to.  It returns null if
754
   *         the key wasn't in this map, or if the mapped value was
755
   *         explicitly set to null.
756
   */
757
  public Object get(Object key)
758
  {
759
    cleanQueue();
760
    WeakBucket.WeakEntry entry = internalGet(key);
761
    return entry == null ? null : entry.getValue();
762
  }
763
 
764
  /**
765
   * Adds a new key/value mapping to this map.
766
   * @param key the key, may be null
767
   * @param value the value, may be null
768
   * @return the value the key was mapped to previously.  It returns
769
   *         null if the key wasn't in this map, or if the mapped value
770
   *         was explicitly set to null.
771
   */
772
  public Object put(Object key, Object value)
773
  {
774
    cleanQueue();
775
    WeakBucket.WeakEntry entry = internalGet(key);
776
    if (entry != null)
777
      return entry.setValue(value);
778
 
779
    modCount++;
780
    if (size >= threshold)
781
      rehash();
782
 
783
    internalAdd(key, value);
784
    return null;
785
  }
786
 
787
  /**
788
   * Removes the key and the corresponding value from this map.
789
   * @param key the key. This may be null.
790
   * @return the value the key was mapped to previously.  It returns
791
   *         null if the key wasn't in this map, or if the mapped value was
792
   *         explicitly set to null.
793
   */
794
  public Object remove(Object key)
795
  {
796
    cleanQueue();
797
    WeakBucket.WeakEntry entry = internalGet(key);
798
    if (entry == null)
799
      return null;
800
 
801
    modCount++;
802
    internalRemove(entry.getBucket());
803
    return entry.getValue();
804
  }
805
 
806
  /**
807
   * Returns a set representation of the entries in this map.  This
808
   * set will not have strong references to the keys, so they can be
809
   * silently removed.  The returned set has therefore the same
810
   * strange behaviour (shrinking size(), disappearing entries) as
811
   * this weak hash map.
812
   * @return a set representation of the entries.
813
   */
814
  public Set entrySet()
815
  {
816
    cleanQueue();
817
    return theEntrySet;
818
  }
819
 
820
  /**
821
   * Clears all entries from this map.
822
   */
823
  public void clear()
824
  {
825
    super.clear();
826
  }
827
 
828
  /**
829
   * Returns true if the map contains at least one key which points to
830
   * the specified object as a value.  Note that the result
831
   * may change spontanously, if its key was only weakly reachable.
832
   * @param value the value to search for
833
   * @return true if it is found in the set.
834
   */
835
  public boolean containsValue(Object value)
836
  {
837
    cleanQueue();
838
    return super.containsValue(value);
839
  }
840
 
841
  /**
842
   * Returns a set representation of the keys in this map.  This
843
   * set will not have strong references to the keys, so they can be
844
   * silently removed.  The returned set has therefore the same
845
   * strange behaviour (shrinking size(), disappearing entries) as
846
   * this weak hash map.
847
   * @return a set representation of the keys.
848
   */
849
  public Set keySet()
850
  {
851
    cleanQueue();
852
    return super.keySet();
853
  }
854
 
855
  /**
856
   * Puts all of the mappings from the given map into this one. If the
857
   * key already exists in this map, its value is replaced.
858
   * @param m the map to copy in
859
   */
860
  public void putAll(Map m)
861
  {
862
    super.putAll(m);
863
  }
864
 
865
  /**
866
   * Returns a collection representation of the values in this map.  This
867
   * collection will not have strong references to the keys, so mappings
868
   * can be silently removed.  The returned collection has therefore the same
869
   * strange behaviour (shrinking size(), disappearing entries) as
870
   * this weak hash map.
871
   * @return a collection representation of the values.
872
   */
873
  public Collection values()
874
  {
875
    cleanQueue();
876
    return super.values();
877
  }
878
} // class WeakHashMap

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.