1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.util;
19
20/**
21 * An AbstractSet is an abstract implementation of the Set interface. This
22 * implementation does not support adding. A subclass must implement the
23 * abstract methods iterator() and size().
24 *
25 * @since 1.2
26 */
27public abstract class AbstractSet<E> extends AbstractCollection<E> implements
28        Set<E> {
29
30    /**
31     * Constructs a new instance of this AbstractSet.
32     */
33    protected AbstractSet() {
34        super();
35    }
36
37    /**
38     * Compares the specified object to this Set and returns true if they are
39     * equal. The object must be an instance of Set and contain the same
40     * objects.
41     *
42     * @param object
43     *            the object to compare with this set.
44     * @return {@code true} if the specified object is equal to this set,
45     *         {@code false} otherwise
46     * @see #hashCode
47     */
48    @Override
49    public boolean equals(Object object) {
50        if (this == object) {
51            return true;
52        }
53        if (object instanceof Set) {
54            Set<?> s = (Set<?>) object;
55
56            try {
57                return size() == s.size() && containsAll(s);
58            } catch (NullPointerException ignored) {
59                return false;
60            } catch (ClassCastException ignored) {
61                return false;
62            }
63        }
64        return false;
65    }
66
67    /**
68     * Returns the hash code for this set. Two set which are equal must return
69     * the same value. This implementation calculates the hash code by adding
70     * each element's hash code.
71     *
72     * @return the hash code of this set.
73     * @see #equals
74     */
75    @Override
76    public int hashCode() {
77        int result = 0;
78        Iterator<?> it = iterator();
79        while (it.hasNext()) {
80            Object next = it.next();
81            result += next == null ? 0 : next.hashCode();
82        }
83        return result;
84    }
85
86    /**
87     * Removes all occurrences in this collection which are contained in the
88     * specified collection.
89     *
90     * @param collection
91     *            the collection of objects to remove.
92     * @return {@code true} if this collection was modified, {@code false}
93     *         otherwise.
94     * @throws UnsupportedOperationException
95     *                if removing from this collection is not supported.
96     */
97    @Override
98    public boolean removeAll(Collection<?> collection) {
99        boolean result = false;
100        if (size() <= collection.size()) {
101            Iterator<?> it = iterator();
102            while (it.hasNext()) {
103                if (collection.contains(it.next())) {
104                    it.remove();
105                    result = true;
106                }
107            }
108        } else {
109            Iterator<?> it = collection.iterator();
110            while (it.hasNext()) {
111                result = remove(it.next()) || result;
112            }
113        }
114        return result;
115    }
116}
117