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    }
35
36    /**
37     * Compares the specified object to this Set and returns true if they are
38     * equal. The object must be an instance of Set and contain the same
39     * objects.
40     *
41     * @param object
42     *            the object to compare with this set.
43     * @return {@code true} if the specified object is equal to this set,
44     *         {@code false} otherwise
45     * @see #hashCode
46     */
47    @Override
48    public boolean equals(Object object) {
49        if (this == object) {
50            return true;
51        }
52        if (object instanceof Set) {
53            Set<?> s = (Set<?>) object;
54
55            try {
56                return size() == s.size() && containsAll(s);
57            } catch (NullPointerException ignored) {
58                return false;
59            } catch (ClassCastException ignored) {
60                return false;
61            }
62        }
63        return false;
64    }
65
66    /**
67     * Returns the hash code for this set. Two set which are equal must return
68     * the same value. This implementation calculates the hash code by adding
69     * each element's hash code.
70     *
71     * @return the hash code of this set.
72     * @see #equals
73     */
74    @Override
75    public int hashCode() {
76        int result = 0;
77        Iterator<?> it = iterator();
78        while (it.hasNext()) {
79            Object next = it.next();
80            result += next == null ? 0 : next.hashCode();
81        }
82        return result;
83    }
84
85    /**
86     * Removes all occurrences in this collection which are contained in the
87     * specified collection.
88     *
89     * @param collection
90     *            the collection of objects to remove.
91     * @return {@code true} if this collection was modified, {@code false}
92     *         otherwise.
93     * @throws UnsupportedOperationException
94     *                if removing from this collection is not supported.
95     */
96    @Override
97    public boolean removeAll(Collection<?> collection) {
98        boolean result = false;
99        if (size() <= collection.size()) {
100            Iterator<?> it = iterator();
101            while (it.hasNext()) {
102                if (collection.contains(it.next())) {
103                    it.remove();
104                    result = true;
105                }
106            }
107        } else {
108            Iterator<?> it = collection.iterator();
109            while (it.hasNext()) {
110                result = remove(it.next()) || result;
111            }
112        }
113        return result;
114    }
115}
116