Implements the Set interface, backed by a ConcurrentHashMap instance : Set « Collections « Java Tutorial






/*
 * 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.
 */

import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * This class implements the <tt>Set</tt> interface, backed by a ConcurrentHashMap instance.
 * 
 * @author Matt Tucker
 * @param <E>
 */
public class ConcurrentHashSet<E> extends AbstractSet<E>
  implements
    Set<E>,
    Cloneable,
    java.io.Serializable
{
  /** */
  private static final long serialVersionUID = 1L;

  private transient ConcurrentHashMap<E, Object> map;

  // Dummy value to associate with an Object in the backing Map
  private static final Object PRESENT = new Object();

  /**
   * Constructs a new, empty set; the backing <tt>ConcurrentHashMap</tt> instance has default
   * initial capacity (16) and load factor (0.75).
   */
  public ConcurrentHashSet()
  {
    map = new ConcurrentHashMap<E, Object>();
  }

  /**
   * Constructs a new set containing the elements in the specified collection. The
   * <tt>ConcurrentHashMap</tt> is created with default load factor (0.75) and an initial capacity
   * sufficient to contain the elements in the specified collection.
   * 
   * @param c
   *            the collection whose elements are to be placed into this set.
   * @throws NullPointerException
   *             if the specified collection is null.
   */
  public ConcurrentHashSet(Collection<? extends E> c)
  {
    map = new ConcurrentHashMap<E, Object>(Math.max((int)(c.size() / .75f) + 1, 16));
    addAll(c);
  }

  /**
   * Constructs a new, empty set; the backing <tt>ConcurrentHashMap</tt> instance has the
   * specified initial capacity and the specified load factor.
   * 
   * @param initialCapacity
   *            the initial capacity of the hash map.
   * @param loadFactor
   *            the load factor of the hash map.
   * @throws IllegalArgumentException
   *             if the initial capacity is less than zero, or if the load factor is nonpositive.
   */
  public ConcurrentHashSet(int initialCapacity, float loadFactor)
  {
    map = new ConcurrentHashMap<E, Object>(initialCapacity, loadFactor, 16);
  }

  /**
   * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has the specified initial
   * capacity and default load factor, which is <tt>0.75</tt>.
   * 
   * @param initialCapacity
   *            the initial capacity of the hash table.
   * @throws IllegalArgumentException
   *             if the initial capacity is less than zero.
   */
  public ConcurrentHashSet(int initialCapacity)
  {
    map = new ConcurrentHashMap<E, Object>(initialCapacity);
  }

  /**
   * 
   * @see java.util.AbstractCollection#iterator()
   */
  @Override
  public Iterator<E> iterator()
  {
    return map.keySet().iterator();
  }

  /**
   * 
   * @see java.util.AbstractCollection#size()
   */
  @Override
  public int size()
  {
    return map.size();
  }

  /**
   * 
   * @see java.util.AbstractCollection#isEmpty()
   */
  @Override
  public boolean isEmpty()
  {
    return map.isEmpty();
  }

  /**
   * 
   * @see java.util.AbstractCollection#contains(java.lang.Object)
   */
  @Override
  public boolean contains(Object o)
  {
    return map.containsKey(o);
  }

  /**
   * 
   * @see java.util.AbstractCollection#add(java.lang.Object)
   */
  @Override
  public boolean add(E o)
  {
    return map.put(o, PRESENT) == null;
  }

  /**
   * 
   * @see java.util.AbstractCollection#remove(java.lang.Object)
   */
  @Override
  public boolean remove(Object o)
  {
    return map.remove(o) == PRESENT;
  }

  /**
   * 
   * @see java.util.AbstractCollection#clear()
   */
  @Override
  public void clear()
  {
    map.clear();
  }

  /**
   * 
   * @see java.lang.Object#clone()
   */
  @SuppressWarnings("unchecked")
  @Override
  public Object clone()
  {
    try
    {
      ConcurrentHashSet<E> newSet = (ConcurrentHashSet<E>)super.clone();
      newSet.map.putAll(map);
      return newSet;
    }
    catch (CloneNotSupportedException e)
    {
      throw new InternalError();
    }
  }

  /**
   * 
   * @param s
   * @throws java.io.IOException
   */
  private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
  {
    s.defaultWriteObject();
    s.writeInt(map.size());

    for (Iterator<E> i = map.keySet().iterator(); i.hasNext();)
    {
      s.writeObject(i.next());
    }
  }

  /**
   * Re-constitute the <tt>HashSet</tt> instance from a stream.
   * 
   * @param inputStream
   * @throws ClassNotFoundException
   * @throws IOException
   */
  private void readObject(ObjectInputStream inputStream) throws ClassNotFoundException,
    IOException
  {
    inputStream.defaultReadObject();

    map = new ConcurrentHashMap<E, Object>();

    int size = inputStream.readInt();
    for (int i = 0; i < size; i++)
    {
      E e = (E)inputStream.readObject();
      map.put(e, PRESENT);
    }
  }
}








9.18.Set
9.18.1.Convert a List to a Set
9.18.2.Convert an ArrayList to HashSet
9.18.3.Creating a Sorted Set
9.18.4.Create new sets from Iterable, var argv
9.18.5.Create an array containing the elements in a set
9.18.6.Comparable with a sorted collection.
9.18.7.Duplicate elements are discarded
9.18.8.Creating a Set That Retains Order-of-Insertion
9.18.9.Convert Set into array
9.18.10.Convert Set into List
9.18.11.Copy all the elements from set2 to set1 (set1 += set2), set1 becomes the union of set1 and set2
9.18.12.Remove all the elements in set1 from set2 (set1 -= set2), set1 becomes the asymmetric difference of set1 and set2
9.18.13.Get the intersection of set1 and set2, set1 becomes the intersection of set1 and set2
9.18.14.Set operations: union, intersection, difference, symmetric difference, is subset, is superset
9.18.15.Remove all elements from a set
9.18.16.List Set
9.18.17.Set implementation that use == instead of equals()
9.18.18.Set union and intersection
9.18.19.Set with values iterated in insertion order.
9.18.20.Implements the Set interface, backed by a ConcurrentHashMap instance
9.18.21.A weak HashSet: element stored in the WeakHashSet might be garbage collected
9.18.22.An IdentitySet that uses reference-equality instead of object-equality
9.18.23.A thin wrapper around a List transforming it into a modifiable Set.
9.18.24.Concurrent set
9.18.25.Set that compares object by identity rather than equality