| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.util; |
| |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.Serializable; |
| |
| /** |
| * HashSet is an implementation of a Set. All optional operations (adding and |
| * removing) are supported. The elements can be any objects. |
| */ |
| public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, |
| Serializable { |
| |
| private static final long serialVersionUID = -5024744406713321676L; |
| |
| transient HashMap<E, HashSet<E>> backingMap; |
| |
| /** |
| * Constructs a new empty instance of {@code HashSet}. |
| */ |
| public HashSet() { |
| this(new HashMap<E, HashSet<E>>()); |
| } |
| |
| /** |
| * Constructs a new instance of {@code HashSet} with the specified capacity. |
| * |
| * @param capacity |
| * the initial capacity of this {@code HashSet}. |
| */ |
| public HashSet(int capacity) { |
| this(new HashMap<E, HashSet<E>>(capacity)); |
| } |
| |
| /** |
| * Constructs a new instance of {@code HashSet} with the specified capacity |
| * and load factor. |
| * |
| * @param capacity |
| * the initial capacity. |
| * @param loadFactor |
| * the initial load factor. |
| */ |
| public HashSet(int capacity, float loadFactor) { |
| this(new HashMap<E, HashSet<E>>(capacity, loadFactor)); |
| } |
| |
| /** |
| * Constructs a new instance of {@code HashSet} containing the unique |
| * elements in the specified collection. |
| * |
| * @param collection |
| * the collection of elements to add. |
| */ |
| public HashSet(Collection<? extends E> collection) { |
| this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection |
| .size() * 2)); |
| for (E e : collection) { |
| add(e); |
| } |
| } |
| |
| HashSet(HashMap<E, HashSet<E>> backingMap) { |
| this.backingMap = backingMap; |
| } |
| |
| /** |
| * Adds the specified object to this {@code HashSet} if not already present. |
| * |
| * @param object |
| * the object to add. |
| * @return {@code true} when this {@code HashSet} did not already contain |
| * the object, {@code false} otherwise |
| */ |
| @Override |
| public boolean add(E object) { |
| return backingMap.put(object, this) == null; |
| } |
| |
| /** |
| * Removes all elements from this {@code HashSet}, leaving it empty. |
| * |
| * @see #isEmpty |
| * @see #size |
| */ |
| @Override |
| public void clear() { |
| backingMap.clear(); |
| } |
| |
| /** |
| * Returns a new {@code HashSet} with the same elements and size as this |
| * {@code HashSet}. |
| * |
| * @return a shallow copy of this {@code HashSet}. |
| * @see java.lang.Cloneable |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public Object clone() { |
| try { |
| HashSet<E> clone = (HashSet<E>) super.clone(); |
| clone.backingMap = (HashMap<E, HashSet<E>>) backingMap.clone(); |
| return clone; |
| } catch (CloneNotSupportedException e) { |
| throw new AssertionError(e); |
| } |
| } |
| |
| /** |
| * Searches this {@code HashSet} for the specified object. |
| * |
| * @param object |
| * the object to search for. |
| * @return {@code true} if {@code object} is an element of this |
| * {@code HashSet}, {@code false} otherwise. |
| */ |
| @Override |
| public boolean contains(Object object) { |
| return backingMap.containsKey(object); |
| } |
| |
| /** |
| * Returns true if this {@code HashSet} has no elements, false otherwise. |
| * |
| * @return {@code true} if this {@code HashSet} has no elements, |
| * {@code false} otherwise. |
| * @see #size |
| */ |
| @Override |
| public boolean isEmpty() { |
| return backingMap.isEmpty(); |
| } |
| |
| /** |
| * Returns an Iterator on the elements of this {@code HashSet}. |
| * |
| * @return an Iterator on the elements of this {@code HashSet}. |
| * @see Iterator |
| */ |
| @Override |
| public Iterator<E> iterator() { |
| return backingMap.keySet().iterator(); |
| } |
| |
| /** |
| * Removes the specified object from this {@code HashSet}. |
| * |
| * @param object |
| * the object to remove. |
| * @return {@code true} if the object was removed, {@code false} otherwise. |
| */ |
| @Override |
| public boolean remove(Object object) { |
| return backingMap.remove(object) != null; |
| } |
| |
| /** |
| * Returns the number of elements in this {@code HashSet}. |
| * |
| * @return the number of elements in this {@code HashSet}. |
| */ |
| @Override |
| public int size() { |
| return backingMap.size(); |
| } |
| |
| private void writeObject(ObjectOutputStream stream) throws IOException { |
| stream.defaultWriteObject(); |
| stream.writeInt(backingMap.table.length); |
| stream.writeFloat(HashMap.DEFAULT_LOAD_FACTOR); |
| stream.writeInt(size()); |
| for (E e : this) { |
| stream.writeObject(e); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void readObject(ObjectInputStream stream) throws IOException, |
| ClassNotFoundException { |
| stream.defaultReadObject(); |
| int length = stream.readInt(); |
| float loadFactor = stream.readFloat(); |
| backingMap = createBackingMap(length, loadFactor); |
| int elementCount = stream.readInt(); |
| for (int i = elementCount; --i >= 0;) { |
| E key = (E) stream.readObject(); |
| backingMap.put(key, this); |
| } |
| } |
| |
| HashMap<E, HashSet<E>> createBackingMap(int capacity, float loadFactor) { |
| return new HashMap<E, HashSet<E>>(capacity, loadFactor); |
| } |
| } |