001: /**
002: * $RCSfile$
003: * $Revision: 42 $
004: * $Date: 2004-10-21 00:28:12 -0700 (Thu, 21 Oct 2004) $
005: *
006: * Copyright (C) 2004 Jive Software. All rights reserved.
007: *
008: * This software is published under the terms of the GNU Public License (GPL),
009: * a copy of which is included in this distribution.
010: */package org.jivesoftware.util;
011:
012: import java.util.*;
013: import java.util.concurrent.ConcurrentHashMap;
014:
015: /**
016: * This class implements the <tt>Set</tt> interface, backed by a ConcurrentHashMap instance.
017: *
018: * @author Matt Tucker
019: */
020: public class ConcurrentHashSet<E> extends AbstractSet<E> implements
021: Set<E>, Cloneable, java.io.Serializable {
022:
023: private transient ConcurrentHashMap<E, Object> map;
024:
025: // Dummy value to associate with an Object in the backing Map
026: private static final Object PRESENT = new Object();
027:
028: /**
029: * Constructs a new, empty set; the backing <tt>ConcurrentHashMap</tt> instance has
030: * default initial capacity (16) and load factor (0.75).
031: */
032: public ConcurrentHashSet() {
033: map = new ConcurrentHashMap<E, Object>();
034: }
035:
036: /**
037: * Constructs a new set containing the elements in the specified
038: * collection. The <tt>ConcurrentHashMap</tt> is created with default load factor
039: * (0.75) and an initial capacity sufficient to contain the elements in
040: * the specified collection.
041: *
042: * @param c the collection whose elements are to be placed into this set.
043: * @throws NullPointerException if the specified collection is null.
044: */
045: public ConcurrentHashSet(Collection<? extends E> c) {
046: map = new ConcurrentHashMap<E, Object>(Math.max(
047: (int) (c.size() / .75f) + 1, 16));
048: addAll(c);
049: }
050:
051: /**
052: * Constructs a new, empty set; the backing <tt>ConcurrentHashMap</tt> instance has
053: * the specified initial capacity and the specified load factor.
054: *
055: * @param initialCapacity the initial capacity of the hash map.
056: * @param loadFactor the load factor of the hash map.
057: * @throws IllegalArgumentException if the initial capacity is less
058: * than zero, or if the load factor is nonpositive.
059: */
060: public ConcurrentHashSet(int initialCapacity, float loadFactor) {
061: map = new ConcurrentHashMap<E, Object>(initialCapacity,
062: loadFactor, 16);
063: }
064:
065: /**
066: * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
067: * the specified initial capacity and default load factor, which is
068: * <tt>0.75</tt>.
069: *
070: * @param initialCapacity the initial capacity of the hash table.
071: * @throws IllegalArgumentException if the initial capacity is less
072: * than zero.
073: */
074: public ConcurrentHashSet(int initialCapacity) {
075: map = new ConcurrentHashMap<E, Object>(initialCapacity);
076: }
077:
078: public Iterator<E> iterator() {
079: return map.keySet().iterator();
080: }
081:
082: public int size() {
083: return map.size();
084: }
085:
086: public boolean isEmpty() {
087: return map.isEmpty();
088: }
089:
090: public boolean contains(Object o) {
091: return map.containsKey(o);
092: }
093:
094: public boolean add(E o) {
095: return map.put(o, PRESENT) == null;
096: }
097:
098: public boolean remove(Object o) {
099: return map.remove(o) == PRESENT;
100: }
101:
102: public void clear() {
103: map.clear();
104: }
105:
106: public Object clone() {
107: try {
108: ConcurrentHashSet<E> newSet = (ConcurrentHashSet<E>) super
109: .clone();
110: newSet.map.putAll(map);
111: return newSet;
112: } catch (CloneNotSupportedException e) {
113: throw new InternalError();
114: }
115: }
116:
117: private void writeObject(java.io.ObjectOutputStream s)
118: throws java.io.IOException {
119: s.defaultWriteObject();
120:
121: // Write out size
122: s.writeInt(map.size());
123:
124: // Write out all elements in the proper order.
125: for (Iterator i = map.keySet().iterator(); i.hasNext();)
126: s.writeObject(i.next());
127: }
128:
129: /**
130: * Reconstitute the <tt>HashSet</tt> instance from a stream (that is,
131: * deserialize it).
132: */
133: private void readObject(java.io.ObjectInputStream s)
134: throws java.io.IOException, ClassNotFoundException {
135: s.defaultReadObject();
136:
137: map = new ConcurrentHashMap<E, Object>();
138:
139: // Read in size
140: int size = s.readInt();
141:
142: // Read in all elements in the proper order.
143: for (int i = 0; i < size; i++) {
144: E e = (E) s.readObject();
145: map.put(e, PRESENT);
146: }
147: }
148: }
|