| AbstractSet.java |
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