You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/12/29 15:54:58 UTC

cvs commit: jakarta-commons/collections/src/java/org/apache/commons/collections/map ReferenceMap.java

scolebourne    2003/12/29 06:54:58

  Modified:    collections/src/java/org/apache/commons/collections/map
                        ReferenceMap.java
  Log:
  Ensure that the keySet and values views handle removed elements
  bug 25551, from Joe Raysa
  
  Revision  Changes    Path
  1.5       +78 -46    jakarta-commons/collections/src/java/org/apache/commons/collections/map/ReferenceMap.java
  
  Index: ReferenceMap.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/map/ReferenceMap.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ReferenceMap.java	28 Dec 2003 16:36:48 -0000	1.4
  +++ ReferenceMap.java	29 Dec 2003 14:54:58 -0000	1.5
  @@ -706,7 +706,7 @@
           if (keySet != null) return keySet;
           keySet = new AbstractSet() {
               public int size() {
  -                return size;
  +                return ReferenceMap.this.size();
               }
   
               public Iterator iterator() {
  @@ -727,6 +727,17 @@
                   ReferenceMap.this.clear();
               }
   
  +            public Object[] toArray() {
  +                return toArray(new Object[0]);
  +            }
  +
  +            public Object[] toArray(Object[] arr) {
  +                Collection c = new ArrayList(size());
  +                for (Iterator it = iterator(); it.hasNext(); ) {
  +                    c.add(it.next());
  +                }
  +                return c.toArray(arr);
  +            }
           };
           return keySet;
       }
  @@ -741,7 +752,7 @@
           if (values != null) return values;
           values = new AbstractCollection()  {
               public int size() {
  -                return size;
  +                return ReferenceMap.this.size();
               }
   
               public void clear() {
  @@ -751,13 +762,29 @@
               public Iterator iterator() {
                   return new ValueIterator();
               }
  +
  +            public Object[] toArray() {
  +                return toArray(new Object[0]);
  +            }
  +
  +            public Object[] toArray(Object[] arr) {
  +                Collection c = new ArrayList(size());
  +                for (Iterator it = iterator(); it.hasNext(); ) {
  +                    c.add(it.next());
  +                }
  +                return c.toArray(arr);
  +            }
           };
           return values;
       }
   
  -
  -    // If getKey() or getValue() returns null, it means
  -    // the mapping is stale and should be removed.
  +    //-----------------------------------------------------------------------
  +    /**
  +     * A MapEntry implementation for the map.
  +     * <p>
  +     * If getKey() or getValue() returns null, it means
  +     * the mapping is stale and should be removed.
  +     */
       private class Entry implements Map.Entry, KeyValue {
   
           Object key;
  @@ -765,7 +792,6 @@
           int hash;
           Entry next;
   
  -
           public Entry(Object key, int hash, Object value, Entry next) {
               this.key = key;
               this.hash = hash;
  @@ -773,54 +799,56 @@
               this.next = next;
           }
   
  -
           public Object getKey() {
               return (keyType > HARD) ? ((Reference)key).get() : key;
           }
   
  -
           public Object getValue() {
               return (valueType > HARD) ? ((Reference)value).get() : value;
           }
   
  -
  -        public Object setValue(Object object) {
  +        public Object setValue(Object obj) {
               Object old = getValue();
  -            if (valueType > HARD) ((Reference)value).clear();
  -            value = toReference(valueType, object, hash);
  +            if (valueType > HARD) {
  +                ((Reference)value).clear();
  +            }
  +            value = toReference(valueType, obj, hash);
               return old;
           }
   
  -
  -        public boolean equals(Object o) {
  -            if (o == null) return false;
  -            if (o == this) return true;
  -            if (!(o instanceof Map.Entry)) return false;
  +        public boolean equals(Object obj) {
  +            if (obj == this) {
  +                return true;
  +            }
  +            if (obj instanceof Map.Entry == false) {
  +                return false;
  +            }
               
  -            Map.Entry entry = (Map.Entry)o;
  +            Map.Entry entry = (Map.Entry)obj;
               Object key = entry.getKey();
               Object value = entry.getValue();
  -            if ((key == null) || (value == null)) return false;
  +            if ((key == null) || (value == null)) {
  +                return false;
  +            }
               return key.equals(getKey()) && value.equals(getValue());
           }
   
  -
           public int hashCode() {
               Object v = getValue();
               return hash ^ ((v == null) ? 0 : v.hashCode());
           }
   
  -
           public String toString() {
               return getKey() + "=" + getValue();
           }
   
  -
           boolean purge(Reference ref) {
               boolean r = (keyType > HARD) && (key == ref);
               r = r || ((valueType > HARD) && (value == ref));
               if (r) {
  -                if (keyType > HARD) ((Reference)key).clear();
  +                if (keyType > HARD) {
  +                    ((Reference)key).clear();
  +                }
                   if (valueType > HARD) {
                       ((Reference)value).clear();
                   } else if (purgeValues) {
  @@ -831,7 +859,9 @@
           }
       }
   
  -
  +    /**
  +     * The EntrySet iterator.
  +     */
       private class EntryIterator implements Iterator {
           // These fields keep track of where we are in the table.
           int index;
  @@ -846,7 +876,6 @@
   
           int expectedModCount;
   
  -
           public EntryIterator() {
               index = (size() != 0 ? table.length : 0);
               // have to do this here!  size() invocation above
  @@ -854,7 +883,6 @@
               expectedModCount = modCount;
           }
   
  -
           public boolean hasNext() {
               checkMod();
               while (nextNull()) {
  @@ -873,26 +901,28 @@
                   }
                   nextKey = e.getKey();
                   nextValue = e.getValue();
  -                if (nextNull()) entry = entry.next;
  +                if (nextNull()) {
  +                    entry = entry.next;
  +                }
               }
               return true;
           }
   
  -
           private void checkMod() {
               if (modCount != expectedModCount) {
                   throw new ConcurrentModificationException();
               }
           }
   
  -
           private boolean nextNull() {
               return (nextKey == null) || (nextValue == null);
           }
   
           protected Entry nextEntry() {    
               checkMod();
  -            if (nextNull() && !hasNext()) throw new NoSuchElementException();
  +            if (nextNull() && !hasNext()) {
  +                throw new NoSuchElementException();
  +            }
               previous = entry;
               entry = entry.next;
               currentKey = nextKey;
  @@ -902,70 +932,72 @@
               return previous;
           }
   
  -
           public Object next() {
               return nextEntry();
           }
   
  -
           public void remove() {
               checkMod();
  -            if (previous == null) throw new IllegalStateException();
  +            if (previous == null) {
  +                throw new IllegalStateException();
  +            }
               ReferenceMap.this.remove(currentKey);
               previous = null;
               currentKey = null;
               currentValue = null;
               expectedModCount = modCount;
           }
  -
       }
   
  -
  +    /**
  +     * The values iterator.
  +     */
       private class ValueIterator extends EntryIterator {
           public Object next() {
               return nextEntry().getValue();
           }
       }
   
  -
  +    /**
  +     * The keySet iterator.
  +     */
       private class KeyIterator extends EntryIterator {
           public Object next() {
               return nextEntry().getKey();
           }
       }
   
  -
  -
  +    //-----------------------------------------------------------------------
       // These two classes store the hashCode of the key of
       // of the mapping, so that after they're dequeued a quick
       // lookup of the bucket in the table can occur.
   
  -
  +    /**
  +     * A soft reference holder.
  +     */
       private static class SoftRef extends SoftReference {
           private int hash;
   
  -
           public SoftRef(int hash, Object r, ReferenceQueue q) {
               super(r, q);
               this.hash = hash;
           }
   
  -
           public int hashCode() {
               return hash;
           }
       }
   
  -
  +    /**
  +     * A weak reference holder.
  +     */
       private static class WeakRef extends WeakReference {
           private int hash;
   
  -
           public WeakRef(int hash, Object r, ReferenceQueue q) {
               super(r, q);
               this.hash = hash;
           }
  -
   
           public int hashCode() {
               return hash;
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org