You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ma...@apache.org on 2002/03/25 06:50:57 UTC

cvs commit: jakarta-commons/collections/src/java/org/apache/commons/collections DefaultMapBag.java HashBag.java TreeBag.java AbstractBag.java

mas         02/03/24 21:50:57

  Modified:    collections/src/java/org/apache/commons/collections
                        HashBag.java TreeBag.java
  Added:       collections/src/java/org/apache/commons/collections
                        DefaultMapBag.java
  Removed:     collections/src/java/org/apache/commons/collections
                        AbstractBag.java
  Log:
  Renamed AbstractBag to DefaultMapBag.  The implementation is more of a
  "default map based implementation" and differs in design from the
  AbstractSet, AbstractMap classes which do not make assumptions about
  how they might be implemented.  To be consistent with JDK AbstractX
  collections, an AbstractBag class should just be providing default
  implementations that could be used regardless of underlying storage
  mechanism.  For example, the add(Object) method would call the abstract
  add(Object,int) method passing the object and 1. Since this
  implementation assumes a Map based storage for the Bag, it does not
  follow the AbstractX pattern, and thus has been renamed.  There is
  still room for future addition of an AbstractBag that does not assume
  a storage data structure.
  
  Revision  Changes    Path
  1.4       +4 -4      jakarta-commons/collections/src/java/org/apache/commons/collections/HashBag.java
  
  Index: HashBag.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/HashBag.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- HashBag.java	13 Mar 2002 05:40:30 -0000	1.3
  +++ HashBag.java	25 Mar 2002 05:50:57 -0000	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/HashBag.java,v 1.3 2002/03/13 05:40:30 mas Exp $
  - * $Revision: 1.3 $
  - * $Date: 2002/03/13 05:40:30 $
  + * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/HashBag.java,v 1.4 2002/03/25 05:50:57 mas Exp $
  + * $Revision: 1.4 $
  + * $Date: 2002/03/25 05:50:57 $
    *
    * ====================================================================
    *
  @@ -70,7 +70,7 @@
    *
    * @author Chuck Burdick
    **/
  -public class HashBag extends AbstractBag implements Bag {
  +public class HashBag extends DefaultMapBag implements Bag {
      public HashBag() {
         setMap(new HashMap());
      }
  
  
  
  1.4       +4 -4      jakarta-commons/collections/src/java/org/apache/commons/collections/TreeBag.java
  
  Index: TreeBag.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/TreeBag.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TreeBag.java	13 Mar 2002 05:40:31 -0000	1.3
  +++ TreeBag.java	25 Mar 2002 05:50:57 -0000	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/TreeBag.java,v 1.3 2002/03/13 05:40:31 mas Exp $
  - * $Revision: 1.3 $
  - * $Date: 2002/03/13 05:40:31 $
  + * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/TreeBag.java,v 1.4 2002/03/25 05:50:57 mas Exp $
  + * $Revision: 1.4 $
  + * $Date: 2002/03/25 05:50:57 $
    *
    * ====================================================================
    *
  @@ -73,7 +73,7 @@
    *
    * @author Chuck Burdick
    **/
  -public class TreeBag extends AbstractBag implements SortedBag, Bag {
  +public class TreeBag extends DefaultMapBag implements SortedBag, Bag {
      public TreeBag() {
         setMap(new TreeMap());
      }
  
  
  
  1.1                  jakarta-commons/collections/src/java/org/apache/commons/collections/DefaultMapBag.java
  
  Index: DefaultMapBag.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/DefaultMapBag.java,v 1.1 2002/03/25 05:50:57 mas Exp $
   * $Revision: 1.1 $
   * $Date: 2002/03/25 05:50:57 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.commons.collections;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.ConcurrentModificationException;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.NoSuchElementException;
  import java.util.Set;
  
  /**
   * This class provides a skeletal implementation of the {@link Bag}
   * interface to minimize the effort required for target implementations.
   * Subclasses need only to call {@link #setMap(Map)} in their constructor 
   * specifying a map instance that will be used to store the contents of 
   * the bag. 
   *
   * @author Chuck Burdick
   * @author <a href="mas@apache.org">Michael A. Smith</a>
   **/
  public abstract class DefaultMapBag implements Bag {
     private Map _map = null;
     private int _total = 0;
     private int _mods = 0;
  
     public boolean add(Object o) {
        return add(o, 1);
     }
  
     public boolean add(Object o, int i) {
        _mods++;
        if (i > 0) {
           int count = (i + getCount(o));
           _map.put(o, new Integer(count));
           _total += i;
           return (count == i);
        } else {
           return false;
        }
     }
  
     public boolean addAll(Collection c) {
        boolean changed = false;
        Iterator i = c.iterator();
        while (i.hasNext()) {
           boolean added = add(i.next());
           changed = changed || added;
        }
        return changed;
     }
  
     public void clear() {
        _mods++;
        _map.clear();
        _total = 0;
     }
  
     public boolean contains(Object o) {
        return _map.containsKey(o);
     }
  
     public boolean containsAll(Collection c) {
        return containsAll(new HashBag(c));
     }
  
     /**
      * Returns <code>true</code> if the bag contains all elements in
      * the given collection, respecting cardinality.
      * @see #containsAll(Collection)
      **/
     public boolean containsAll(Bag other) {
        boolean result = true;
        Iterator i = other.uniqueSet().iterator();
        while (i.hasNext()) {
           Object current = i.next();
           boolean contains =
              getCount(current) >= ((Bag)other).getCount(current);
           result = result && contains;
        }
        return result;
     }
  
     public boolean equals(Object o) {
        return (o == this || 
                (o != null && o.getClass().equals(this.getClass()) &&
                 ((DefaultMapBag)o)._map.equals(this._map)));
     }
  
     public int hashCode() {
        return _map.hashCode();
     }
  
     public boolean isEmpty() {
        return _map.isEmpty();
     }
  
     public Iterator iterator() {
        return new BagIterator(this, extractList().iterator()); 
     }
  
     private class BagIterator implements Iterator {
        private DefaultMapBag _parent = null;
        private Iterator _support = null;
        private Object _current = null;
        private int _mods = 0;
  
        public BagIterator(DefaultMapBag parent, Iterator support) {
           _parent = parent;
           _support = support;
           _current = null;
           _mods = parent.modCount();
        }
  
        public boolean hasNext() {
           return _support.hasNext();
        }
  
        public Object next() {
           if (_parent.modCount() != _mods) {
              throw new ConcurrentModificationException();
           }
           _current = _support.next();
           return _current;
        }
        
        public void remove() {
           if (_parent.modCount() != _mods) {
              throw new ConcurrentModificationException();
           }
           _support.remove();
           _parent.remove(_current, 1);
           _mods++;
        }
     }
  
     public boolean remove (Object o) {
        return remove(o, getCount(o));
     }
  
     public boolean remove (Object o, int i) {
        _mods++;
        boolean result = false;
        int count = getCount(o);
        if (i <= 0) {
           result = false;
        } else if (count > i) {
           _map.put(o, new Integer(count - i));
           result = true;
           _total -= i;
        } else { // count > 0 && count <= i  
           // need to remove all
           result = (_map.remove(o) != null);
           _total -= count;
        }
        return result;
     }
  
     public boolean removeAll(Collection c) {
        boolean result = false;
        if (c != null) {
           Iterator i = c.iterator();
           while (i.hasNext()) {
              boolean changed = remove(i.next(), 1);
              result = result || changed;
           }
        }
        return result;
     }
  
     public boolean retainAll(Collection c) {
        return retainAll(new HashBag(c));
     }
  
     /**
      * Remove any members of the bag that are not in the given
      * bag, respecting cardinality.
      * @see #retainAll(Collection)
      * @return <code>true</code> if this call changed the collection
      **/
     public boolean retainAll(Bag other) {
        boolean result = false;
        Bag excess = new HashBag();
        Iterator i = uniqueSet().iterator();
        while (i.hasNext()) {
           Object current = i.next();
           int myCount = getCount(current);
           int otherCount = other.getCount(current);
           if (1 <= otherCount && otherCount <= myCount) {
              excess.add(current, myCount - otherCount);
           } else {
              excess.add(current, myCount);
           }
        }
        if (!excess.isEmpty()) {
           result = removeAll(excess);
        }
        return result;
     }
  
     public Object[] toArray() {
        return extractList().toArray();
     }
  
     public Object[] toArray(Object[] a) {
        return extractList().toArray(a);
     }
  
     public int getCount(Object o) {
        int result = 0;
        Integer count = MapUtils.getInteger(_map, o);
        if (count != null) {
           result = count.intValue();
        }
        return result;
     }
  
     public Set uniqueSet() {
        return Collections.unmodifiableSet(_map.keySet());
     }
  
     public int size() {
        return _total;
     }
  
     /**
      * Actually walks the bag to make sure the count is correct and
      * resets the running total
      **/
     protected int calcTotalSize() {
        _total = extractList().size();
        return _total;
     }
  
     /**
      * Utility method for implementations to set the map that backs
      * this bag. Not intended for interactive use outside of
      * subclasses.
      **/
     protected void setMap(Map m) {
        _map = m;
     }
  
     /**
      * Utility method for implementations to access the map that backs
      * this bag. Not intended for interactive use outside of
      * subclasses.
      **/
     protected Map getMap() {
        return _map;
     }
  
     /**
      * Create a list for use in iteration, etc.
      **/
     private List extractList() {
        List result = new ArrayList();
        Iterator i = uniqueSet().iterator();
        while (i.hasNext()) {
           Object current = i.next();
           for (int index = getCount(current); index > 0; index--) {
              result.add(current);
           }
        }
        return result;
     }
  
     /**
      * Return number of modifications for iterator
      **/
     private int modCount() {
        return _mods;
     }
  }
  
  
  
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>