001 /******************************************************************************* 002 * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 Sebastian 003 * Thomschke. 004 * 005 * All Rights Reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 * Contributors: 011 * Sebastian Thomschke - initial implementation. 012 *******************************************************************************/ 013 package net.sf.oval.internal.util; 014 015 import static net.sf.oval.Validator.getCollectionFactory; 016 017 import java.io.ObjectInputStream; 018 import java.io.ObjectOutputStream; 019 import java.io.Serializable; 020 import java.util.Collection; 021 import java.util.Iterator; 022 import java.util.Map; 023 import java.util.Set; 024 025 /** 026 * @author Sebastian Thomschke 027 */ 028 public final class IdentitySet<E> implements Set<E>, Serializable 029 { 030 private static final long serialVersionUID = 1L; 031 032 private transient Map<Integer, E> map; 033 034 /** 035 * Constructs a new, empty <tt>IdentitySet</tt>; the backing <tt>Map</tt> instance has 036 * default initial capacity (16) and load factor (0.75). 037 */ 038 public IdentitySet() 039 { 040 map = getCollectionFactory().createMap(); 041 } 042 043 /** 044 * Constructs a new, empty <tt>IdentitySet</tt>; the backing <tt>Map</tt> instance has 045 * the given initial capacity and the default load factor (0.75). 046 */ 047 public IdentitySet(final int initialCapacity) 048 { 049 map = getCollectionFactory().createMap(initialCapacity); 050 } 051 052 /** 053 * {@inheritDoc} 054 */ 055 public boolean add(final E o) 056 { 057 final int hash = System.identityHashCode(o); 058 return map.put(hash, o) == null; 059 } 060 061 /** 062 * {@inheritDoc} 063 */ 064 public boolean addAll(final Collection< ? extends E> c) 065 { 066 int count = 0; 067 for (final E e : c) 068 if (add(e)) count++; 069 return count > 0; 070 } 071 072 /** 073 * {@inheritDoc} 074 */ 075 public void clear() 076 { 077 map.clear(); 078 } 079 080 /** 081 * {@inheritDoc} 082 */ 083 public boolean contains(final Object o) 084 { 085 final int hash = System.identityHashCode(o); 086 return map.containsKey(hash); 087 } 088 089 /** 090 * {@inheritDoc} 091 */ 092 public boolean containsAll(final Collection< ? > c) 093 { 094 throw new UnsupportedOperationException(); 095 } 096 097 /** 098 * {@inheritDoc} 099 */ 100 public boolean isEmpty() 101 { 102 return map.isEmpty(); 103 } 104 105 /** 106 * {@inheritDoc} 107 */ 108 public Iterator<E> iterator() 109 { 110 return map.values().iterator(); 111 } 112 113 /** 114 * Reads the <tt>IdentitySet</tt> instance from a stream. 115 */ 116 @SuppressWarnings("unchecked") 117 private void readObject(final ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException 118 { 119 // materialize any hidden serialization magic 120 ois.defaultReadObject(); 121 122 // materialize the size 123 final int size = ois.readInt(); 124 125 // materialize the elements 126 map = getCollectionFactory().createMap(size); 127 for (int i = 0; i < size; i++) 128 { 129 final E o = (E) ois.readObject(); 130 final int hash = System.identityHashCode(o); 131 map.put(hash, o); 132 } 133 } 134 135 /** 136 * {@inheritDoc} 137 */ 138 public boolean remove(final Object o) 139 { 140 final int hash = System.identityHashCode(o); 141 return map.remove(hash) != null; 142 } 143 144 /** 145 * {@inheritDoc} 146 */ 147 public boolean removeAll(final Collection< ? > c) 148 { 149 boolean modified = false; 150 for (final Object e : c) 151 if (remove(e)) modified = true; 152 return modified; 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 public boolean retainAll(final Collection< ? > c) 159 { 160 throw new UnsupportedOperationException(); 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 public int size() 167 { 168 return map.size(); 169 } 170 171 /** 172 * {@inheritDoc} 173 */ 174 public Object[] toArray() 175 { 176 return map.values().toArray(); 177 } 178 179 /** 180 * {@inheritDoc} 181 */ 182 public <T> T[] toArray(final T[] a) 183 { 184 return map.values().toArray(a); 185 } 186 187 /** 188 * Writes state of this <tt>IdentitySet</tt> instance to a stream. 189 */ 190 private void writeObject(final ObjectOutputStream oos) throws java.io.IOException 191 { 192 // serialize any hidden serialization magic 193 oos.defaultWriteObject(); 194 195 // serialize the set's size 196 oos.writeInt(map.size()); 197 198 // serialize the set's elements 199 for (final E e : map.values()) 200 oos.writeObject(e); 201 } 202 }