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 java.lang.Boolean.TRUE; 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.Set; 023 import java.util.WeakHashMap; 024 025 /** 026 * @author Sebastian Thomschke 027 */ 028 public final class WeakHashSet<E> implements Set<E>, Serializable 029 { 030 private static final long serialVersionUID = 1L; 031 032 private transient WeakHashMap<E, Object> map; 033 034 /** 035 * Constructs a new, empty <tt>WeakHashSet</tt>; the backing <tt>WeakHashMap</tt> instance has 036 * default initial capacity (16) and load factor (0.75). 037 */ 038 public WeakHashSet() 039 { 040 map = new WeakHashMap<E, Object>(); 041 } 042 043 /** 044 * Constructs a new, empty <tt>WeakHashSet</tt>; the backing <tt>WeakHashMap</tt> instance has 045 * the given initial capacity and the default load factor (0.75). 046 */ 047 public WeakHashSet(final int initialCapacity) 048 { 049 map = new WeakHashMap<E, Object>(initialCapacity); 050 } 051 052 /** 053 * {@inheritDoc} 054 */ 055 public boolean add(final E o) 056 { 057 return map.put(o, TRUE) == null; 058 } 059 060 /** 061 * {@inheritDoc} 062 */ 063 public boolean addAll(final Collection< ? extends E> c) 064 { 065 int count = 0; 066 for (final E e : c) 067 if (add(e)) count++; 068 return count > 0; 069 } 070 071 public void clear() 072 { 073 map.clear(); 074 } 075 076 /** 077 * {@inheritDoc} 078 */ 079 public boolean contains(final Object o) 080 { 081 return map.containsKey(o); 082 } 083 084 /** 085 * {@inheritDoc} 086 */ 087 public boolean containsAll(final Collection< ? > c) 088 { 089 return map.keySet().containsAll(c); 090 } 091 092 /** 093 * {@inheritDoc} 094 */ 095 @Override 096 public boolean equals(final Object o) 097 { 098 if (o == this) return true; 099 100 if (!(o instanceof Set< ? >)) return false; 101 102 final Set< ? > set = (Set< ? >) o; 103 104 if (set.size() != size()) return false; 105 106 return containsAll(set); 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 @Override 113 public int hashCode() 114 { 115 int hash = 0; 116 for (final E e : map.keySet()) 117 if (e != null) hash += e.hashCode(); 118 return hash; 119 } 120 121 /** 122 * {@inheritDoc} 123 */ 124 public boolean isEmpty() 125 { 126 return map.isEmpty(); 127 } 128 129 /** 130 * {@inheritDoc} 131 */ 132 public Iterator<E> iterator() 133 { 134 return map.keySet().iterator(); 135 } 136 137 /** 138 * Reads the <tt>WeakHashSet</tt> instance from a stream. 139 */ 140 @SuppressWarnings("unchecked") 141 private void readObject(final ObjectInputStream ois) throws java.io.IOException, ClassNotFoundException 142 { 143 // materialize any hidden serialization magic 144 ois.defaultReadObject(); 145 146 // materialize the size 147 final int size = ois.readInt(); 148 149 // materialize the elements 150 map = new WeakHashMap<E, Object>(size); 151 for (int i = 0; i < size; i++) 152 map.put((E) ois.readObject(), TRUE); 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 public boolean remove(final Object o) 159 { 160 return map.remove(o) == TRUE; 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 public boolean removeAll(final Collection< ? > c) 167 { 168 return map.keySet().removeAll(c); 169 } 170 171 /** 172 * {@inheritDoc} 173 */ 174 public boolean retainAll(final Collection< ? > c) 175 { 176 return map.keySet().retainAll(c); 177 } 178 179 /** 180 * {@inheritDoc} 181 */ 182 public int size() 183 { 184 return map.size(); 185 } 186 187 /** 188 * {@inheritDoc} 189 */ 190 public Object[] toArray() 191 { 192 return map.keySet().toArray(); 193 } 194 195 /** 196 * {@inheritDoc} 197 */ 198 public <T> T[] toArray(final T[] a) 199 { 200 return map.keySet().toArray(a); 201 } 202 203 /** 204 * Writes the state of this <tt>WeakHashSet</tt> instance to a stream. 205 */ 206 private void writeObject(final ObjectOutputStream oos) throws java.io.IOException 207 { 208 // serialize any hidden serialization magic 209 oos.defaultWriteObject(); 210 211 // serialize the set's size 212 oos.writeInt(map.size()); 213 214 // serialize the set's elements 215 for (final E e : map.keySet()) 216 oos.writeObject(e); 217 } 218 }