1   /*
2    * %W% %E%
3    *
4    * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5    * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6    */
7   
8   package java.util;
9   
10  /**
11   * This class provides a skeletal implementation of the <tt>Set</tt>
12   * interface to minimize the effort required to implement this
13   * interface. <p>
14   *
15   * The process of implementing a set by extending this class is identical
16   * to that of implementing a Collection by extending AbstractCollection,
17   * except that all of the methods and constructors in subclasses of this
18   * class must obey the additional constraints imposed by the <tt>Set</tt>
19   * interface (for instance, the add method must not permit addition of
20   * multiple instances of an object to a set).<p>
21   *
22   * Note that this class does not override any of the implementations from
23   * the <tt>AbstractCollection</tt> class.  It merely adds implementations
24   * for <tt>equals</tt> and <tt>hashCode</tt>.<p>
25   *
26   * This class is a member of the
27   * <a href="{@docRoot}/../technotes/guides/collections/index.html">
28   * Java Collections Framework</a>.
29   *
30   * @param <E> the type of elements maintained by this set
31   *
32   * @author  Josh Bloch
33   * @author  Neal Gafter
34   * @version %I%, %G%
35   * @see Collection
36   * @see AbstractCollection
37   * @see Set
38   * @since 1.2
39   */
40  
41  public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
42      /**
43       * Sole constructor.  (For invocation by subclass constructors, typically
44       * implicit.)
45       */
46      protected AbstractSet() {
47      }
48  
49      // Comparison and hashing
50  
51      /**
52       * Compares the specified object with this set for equality.  Returns
53       * <tt>true</tt> if the given object is also a set, the two sets have
54       * the same size, and every member of the given set is contained in
55       * this set.  This ensures that the <tt>equals</tt> method works
56       * properly across different implementations of the <tt>Set</tt>
57       * interface.<p>
58       *
59       * This implementation first checks if the specified object is this
60       * set; if so it returns <tt>true</tt>.  Then, it checks if the
61       * specified object is a set whose size is identical to the size of
62       * this set; if not, it returns false.  If so, it returns
63       * <tt>containsAll((Collection) o)</tt>.
64       *
65       * @param o object to be compared for equality with this set
66       * @return <tt>true</tt> if the specified object is equal to this set
67       */
68      public boolean equals(Object o) {
69      if (o == this)
70          return true;
71  
72      if (!(o instanceof Set))
73          return false;
74      Collection c = (Collection) o;
75      if (c.size() != size())
76          return false;
77          try {
78              return containsAll(c);
79          } catch (ClassCastException unused)   {
80              return false;
81          } catch (NullPointerException unused) {
82              return false;
83          }
84      }
85  
86      /**
87       * Returns the hash code value for this set.  The hash code of a set is
88       * defined to be the sum of the hash codes of the elements in the set,
89       * where the hash code of a <tt>null</tt> element is defined to be zero.
90       * This ensures that <tt>s1.equals(s2)</tt> implies that
91       * <tt>s1.hashCode()==s2.hashCode()</tt> for any two sets <tt>s1</tt>
92       * and <tt>s2</tt>, as required by the general contract of
93       * {@link Object#hashCode}.
94       *
95       * <p>This implementation iterates over the set, calling the
96       * <tt>hashCode</tt> method on each element in the set, and adding up
97       * the results.
98       *
99       * @return the hash code value for this set
100      * @see Object#equals(Object)
101      * @see Set#equals(Object)
102      */
103     public int hashCode() {
104     int h = 0;
105     Iterator<E> i = iterator();
106     while (i.hasNext()) {
107         E obj = i.next();
108             if (obj != null)
109                 h += obj.hashCode();
110         }
111     return h;
112     }
113 
114     /**
115      * Removes from this set all of its elements that are contained in the
116      * specified collection (optional operation).  If the specified
117      * collection is also a set, this operation effectively modifies this
118      * set so that its value is the <i>asymmetric set difference</i> of
119      * the two sets.
120      *
121      * <p>This implementation determines which is the smaller of this set
122      * and the specified collection, by invoking the <tt>size</tt>
123      * method on each.  If this set has fewer elements, then the
124      * implementation iterates over this set, checking each element
125      * returned by the iterator in turn to see if it is contained in
126      * the specified collection.  If it is so contained, it is removed
127      * from this set with the iterator's <tt>remove</tt> method.  If
128      * the specified collection has fewer elements, then the
129      * implementation iterates over the specified collection, removing
130      * from this set each element returned by the iterator, using this
131      * set's <tt>remove</tt> method.
132      *
133      * <p>Note that this implementation will throw an
134      * <tt>UnsupportedOperationException</tt> if the iterator returned by the
135      * <tt>iterator</tt> method does not implement the <tt>remove</tt> method.
136      *
137      * @param  c collection containing elements to be removed from this set
138      * @return <tt>true</tt> if this set changed as a result of the call
139      * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation
140      *         is not supported by this set
141      * @throws ClassCastException if the class of an element of this set
142      *         is incompatible with the specified collection (optional)
143      * @throws NullPointerException if this set contains a null element and the
144      *         specified collection does not permit null elements (optional),
145      *         or if the specified collection is null
146      * @see #remove(Object)
147      * @see #contains(Object)
148      */
149     public boolean removeAll(Collection<?> c) {
150         boolean modified = false;
151 
152         if (size() > c.size()) {
153             for (Iterator<?> i = c.iterator(); i.hasNext(); )
154                 modified |= remove(i.next());
155         } else {
156             for (Iterator<?> i = iterator(); i.hasNext(); ) {
157                 if (c.contains(i.next())) {
158                     i.remove();
159                     modified = true;
160                 }
161             }
162         }
163         return modified;
164     }
165 
166 }
167