zcommon/src/main/java/org/zkoss/util/IdentityHashSet.java

Summary

Maintainability
A
0 mins
Test Coverage
/* 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);
        }
    }
}