/* IdentityHashSet.java
Purpose:
Description:
History:
Fri Sep 13 11:18:11 2002, Created by tomyeh
Copyright (C) 2002 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
This program is distributed under LGPL Version 2.1 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.util;
import java.util.Collection;
import java.util.Set;
import java.util.AbstractSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import org.zkoss.lang.Objects;
/**
* Like java.util.InternalHashMap, it uses == and System.identityHashCode
* for doing HashSet.
*
* @author tomyeh
* @see IdentityComparator
*/
public class IdentityHashSet<T> extends AbstractSet<T>
implements Set<T>, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 20060622L;
private transient IdentityHashMap<T, Object> _map;
/**
* Constructs a new, empty set; the backing <tt>IdentityHashMap</tt>
* instance has default capacity (32).
*/
public IdentityHashSet() {
_map = new IdentityHashMap<T, Object>();
}
/**
* Constructs a new set containing 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 IdentityHashSet(Collection<T> c) {
_map = new IdentityHashMap<T, Object>(Math.max((c.size()*4)/3, 16));
addAll(c);
}
/**
* Constructs a new, empty set with the specified expected maximum size.
*
* @param expectedMaxSize the expected maximum size of the map.
* @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
*/
public IdentityHashSet(int expectedMaxSize) {
_map = new IdentityHashMap<T, Object>(expectedMaxSize);
}
//-- Set --//
public Iterator<T> iterator() {
return _map.keySet().iterator();
}
public int size() {
return _map.size();
}
public boolean isEmpty() {
return _map.isEmpty();
}
public boolean contains(Object o) {
return _map.containsKey(o);
}
public boolean add(T o) {
return _map.put(o, Objects.UNKNOWN)==null;
}
public boolean remove(Object o) {
return _map.remove(o)==Objects.UNKNOWN;
}
public void clear() {
_map.clear();
}
@SuppressWarnings("unchecked")
public Object clone() {
try {
IdentityHashSet<T> newSet = (IdentityHashSet<T>)super.clone();
newSet._map = (IdentityHashMap<T, Object>)_map.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
//-- Serializable --//
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out size
s.writeInt(_map.size());
// Write out all elements in the proper order.
for (T key: _map.keySet())
s.writeObject(key);
}
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size (number of Mappings)
int size = s.readInt();
// Read in IdentityHashMap capacity and load factor and create backing IdentityHashMap
_map = new IdentityHashMap<T, Object>((size*4)/3);
// Allow for 33% growth (i.e., capacity is >= 2* size()).
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
Object e = s.readObject();
_map.put((T)e, Objects.UNKNOWN);
}
}
}