1 module java.util.HashSet; 2 3 import java.lang.all; 4 import java.util.Set; 5 import java.util.Collection; 6 import java.util.Iterator; 7 8 version(Tango){ 9 static import tango.util.container.HashSet; 10 } else { // Phobos 11 } 12 13 /** 14 * This class implements the {@code Set} interface, backed by a hash table 15 * (actually a {@code HashMap} instance). It makes no guarantees as to the 16 * iteration order of the set; in particular, it does not guarantee that the 17 * order will remain constant over time. This class permits the {@code null} 18 * element. 19 */ 20 class HashSet : Set { 21 version(Tango){ 22 alias tango.util.container.HashSet.HashSet!(Object) SetType; 23 private SetType set; 24 } else { // Phobos 25 alias SetType = void[0][Object]; 26 private SetType set; 27 } 28 29 /** 30 * Constructs a new, empty set. 31 */ 32 public this(){ 33 version(Tango){ 34 set = new SetType(); 35 } else { // Phobos 36 // already initialized (to null) 37 } 38 } 39 40 /** 41 * Constructs a new set containing the elements in the specified 42 * collection. 43 * 44 * @param c the collection whose elements are to be placed into this set. 45 */ 46 public this(Collection c){ 47 version(Tango){ 48 set = new SetType(); 49 addAll(c); 50 } else { // Phobos 51 // already initialized (to null) 52 this.addAll(c); 53 } 54 } 55 56 /** 57 * Constructs a new, empty set. 58 * 59 * D2/Phobos: This method has no difference compared to `this()`. 60 * 61 * @param initialCapacity the initial capacity of the hash table. 62 */ 63 public this(int initialCapacity){ 64 version(Tango){ 65 set = new SetType(); 66 } else { // Phobos 67 // already initialized (to null) 68 } 69 } 70 71 /** 72 * Constructs a new, empty set. 73 * 74 * D2/Phobos: This method has no difference compared to `this()`. 75 * 76 * @param initialCapacity the initial capacity of the hash map 77 * @param loadFactor the load factor of the hash map 78 */ 79 public this(int initialCapacity, float loadFactor){ 80 version(Tango){ 81 set = new SetType(loadFactor); 82 } else { // Phobos 83 // already initialized (to null) 84 } 85 } 86 87 /** 88 * Adds the specified element to this set if it is not already present. 89 * More formally, adds the specified element {@code e} to this set if 90 * this set contains no element {@code e2} such that 91 * {@code Objects.equals(e, e2)}. 92 * If this set already contains the element, the call leaves the set 93 * unchanged and returns {@code false}. 94 * 95 * @param e element to be added to this set 96 * @return {@code true} if this set did not already contain the specified 97 * element 98 */ 99 public bool add(Object o) { 100 version(Tango) { 101 return set.add(o); 102 } else { // Phobos 103 static if (__traits(hasMember, .object, "update")) 104 { 105 bool res = false; 106 set.update(o, { 107 res = true; 108 return (void[0]).init; 109 }, (ref void[0] v) { 110 /* Keep "return" for D versions < 2.092.0 */ 111 return v; 112 }); 113 return res; 114 } 115 else 116 { 117 /* D versions < 2.082.0 */ 118 if (this.contains(o)) return false; 119 set[o] = (void[0]).init; 120 return true; 121 } 122 } 123 } 124 125 /// Ditto 126 public bool add(String o) { 127 return add(stringcast(o)); 128 } 129 130 /** 131 * Adds all of the elements in the specified collection to this set if 132 * they're not already present (optional operation). If the specified 133 * collection is also a set, the {@code addAll} operation effectively 134 * modifies this set so that its value is the <i>union</i> of the two 135 * sets. The behavior of this operation is undefined if the specified 136 * collection is modified while the operation is in progress. 137 * 138 * @param c collection containing elements to be added to this set 139 * @return {@code true} if this set changed as a result of the call 140 * 141 * @throws UnsupportedOperationException if the {@code addAll} operation 142 * is not supported by this set 143 * @throws ClassCastException if the class of an element of the 144 * specified collection prevents it from being added to this set 145 * @throws NullPointerException if the specified collection contains one 146 * or more null elements and this set does not permit null 147 * elements, or if the specified collection is null 148 * @throws IllegalArgumentException if some property of an element of the 149 * specified collection prevents it from being added to this set 150 * @see #add(Object) 151 */ 152 public bool addAll(Collection c) { 153 bool res = false; 154 foreach( o; c ){ 155 res |= add(o); 156 } 157 return res; 158 } 159 160 /** 161 * Removes all of the elements from this set. 162 * The set will be empty after this call returns. 163 */ 164 public void clear() { 165 version(Tango) { 166 set.clear(); 167 } else { // Phobos 168 set.clear(); 169 } 170 } 171 172 /** 173 * Returns {@code true} if this set contains the specified element. 174 * More formally, returns {@code true} if and only if this set 175 * contains an element {@code e} such that 176 * {@code Objects.equals(o, e)}. 177 * 178 * @param o element whose presence in this set is to be tested 179 * @return {@code true} if this set contains the specified element 180 */ 181 public bool contains(Object o){ 182 version(Tango){ 183 return set.contains(o); 184 } else { // Phobos 185 foreach (e; set.byKey) 186 { 187 if (o is null && e is null) return true; 188 if (o == e) return true; 189 } 190 return false; 191 } 192 } 193 194 /// Ditto 195 public bool contains(String o) { 196 return contains(stringcast(o)); 197 } 198 199 public bool containsAll(Collection c){ 200 implMissing( __FILE__, __LINE__ ); 201 return false; 202 } 203 public override equals_t opEquals(Object o){ 204 implMissing( __FILE__, __LINE__ ); 205 return 0; 206 } 207 public override hash_t toHash(){ 208 implMissingSafe( __FILE__, __LINE__ ); 209 return 0; 210 } 211 212 /** 213 * Returns {@code true} if this set contains no elements. 214 * 215 * @return {@code true} if this set contains no elements 216 */ 217 public bool isEmpty() { 218 version(Tango){ 219 return set.isEmpty(); 220 } else { // Phobos 221 import std.range : empty; 222 return empty(set); 223 } 224 } 225 226 version(Tango){ 227 class LocalIterator : Iterator { 228 SetType.Iterator iter; 229 Object nextElem; 230 this( SetType.Iterator iter){ 231 this.iter = iter; 232 } 233 public bool hasNext(){ 234 return iter.next(nextElem); 235 } 236 public Object next(){ 237 return nextElem; 238 } 239 public void remove(){ 240 iter.remove(); 241 } 242 } 243 } else { // Phobos 244 } 245 public Iterator iterator(){ 246 version(Tango){ 247 return new LocalIterator(set.iterator()); 248 } else { // Phobos 249 implMissingInPhobos(); 250 return null; 251 } 252 } 253 254 /** 255 * Removes the specified element from this set if it is present. 256 * More formally, removes an element {@code e} such that 257 * {@code Objects.equals(o, e)}, 258 * if this set contains such an element. Returns {@code true} if 259 * this set contained the element (or equivalently, if this set 260 * changed as a result of the call). (This set will not contain the 261 * element once the call returns.) 262 * 263 * @param o object to be removed from this set, if present 264 * @return {@code true} if the set contained the specified element 265 */ 266 public bool remove(Object o) { 267 version(Tango) { 268 return set.remove(o); 269 } else { // Phobos 270 return set.remove(o); 271 } 272 } 273 274 /// Ditto 275 public bool remove(String o){ 276 return remove(stringcast(o)); 277 } 278 279 public bool removeAll(Collection c){ 280 implMissing( __FILE__, __LINE__ ); 281 return false; 282 } 283 public bool retainAll(Collection c){ 284 implMissing( __FILE__, __LINE__ ); 285 return false; 286 } 287 288 /** 289 * Returns the number of elements in this set (its cardinality). 290 * 291 * @return the number of elements in this set (its cardinality) 292 */ 293 public int size(){ 294 version(Tango){ 295 return set.size(); 296 } else { // Phobos 297 return cast(int)set.length; 298 } 299 } 300 301 /** 302 * Returns an array containing all of the elements in this set. 303 * If this set makes any guarantees as to what order its elements 304 * are returned by its iterator, this method must return the 305 * elements in the same order. 306 * 307 * <p>The returned array will be "safe" in that no references to it 308 * are maintained by this set. (In other words, this method must 309 * allocate a new array even if this set is backed by an array). 310 * The caller is thus free to modify the returned array. 311 * 312 * <p>This method acts as bridge between array-based and collection-based 313 * APIs. 314 * 315 * @return an array containing all the elements in this set 316 */ 317 public Object[] toArray(){ 318 version(Tango){ 319 Object[] res; 320 res.length = size(); 321 int idx = 0; 322 foreach( o; set ){ 323 res[idx] = o; 324 idx++; 325 } 326 return res; 327 } else { // Phobos 328 return set.keys; 329 } 330 } 331 332 public Object[] toArray(Object[] a){ 333 implMissing( __FILE__, __LINE__ ); 334 return null; 335 } 336 public override String toString(){ 337 implMissing( __FILE__, __LINE__ ); 338 return null; 339 } 340 341 // only for D 342 public int opApply (int delegate(ref Object value) dg){ 343 version(Tango){ 344 return set.opApply(dg); 345 } else { // Phobos 346 int result = 0; 347 foreach(e; set.byKey) { 348 result = dg(e); 349 350 if (result) 351 break; 352 } 353 return result; 354 } 355 } 356 }