1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.collection.AbstractSet; 13 14 15 import hunt.collection.AbstractCollection; 16 import hunt.collection.Collection; 17 import hunt.collection.Set; 18 19 import hunt.Exceptions; 20 import hunt.Object; 21 import hunt.Exceptions; 22 23 24 /** 25 * This class provides a skeletal implementation of the <tt>Set</tt> 26 * interface to minimize the effort required to implement this 27 * interface. <p> 28 * 29 * The process of implementing a set by extending this class is identical 30 * to that of implementing a Collection by extending AbstractCollection, 31 * except that all of the methods and constructors in subclasses of this 32 * class must obey the additional constraints imposed by the <tt>Set</tt> 33 * interface (for instance, the add method must not permit addition of 34 * multiple instances of an object to a set).<p> 35 * 36 * Note that this class does not override any of the implementations from 37 * the <tt>AbstractCollection</tt> class. It merely adds implementations 38 * for <tt>equals</tt> and <tt>hashCode</tt>.<p> 39 * 40 * This class is a member of the 41 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 42 * Java Collections Framework</a>. 43 * 44 * @param !(E) the type of elements maintained by this set 45 * 46 * @see Collection 47 * @see AbstractCollection 48 * @see Set 49 */ 50 abstract class AbstractSet(E) : AbstractCollection!E, Set!E { 51 /** 52 * Sole constructor. (For invocation by subclass constructors, typically 53 * implicit.) 54 */ 55 protected this() { 56 } 57 58 // Comparison and hashing 59 60 /** 61 * Compares the specified object with this set for equality. Returns 62 * <tt>true</tt> if the given object is also a set, the two sets have 63 * the same size, and every member of the given set is contained in 64 * this set. This ensures that the <tt>equals</tt> method works 65 * properly across different implementations of the <tt>Set</tt> 66 * interface.<p> 67 * 68 * This implementation first checks if the specified object is this 69 * set; if so it returns <tt>true</tt>. Then, it checks if the 70 * specified object is a set whose size is identical to the size of 71 * this set; if not, it returns false. If so, it returns 72 * <tt>containsAll((Collection) o)</tt>. 73 * 74 * @param o object to be compared for equality with this set 75 * @return <tt>true</tt> if the specified object is equal to this set 76 */ 77 override bool opEquals(Object o) { 78 if (o is this) 79 return true; 80 81 Collection!E c = cast(Collection!E) o; 82 if(c is null) return false; 83 if (c.size() != size()) 84 return false; 85 86 try { 87 return containsAll(c); 88 } catch (Exception) { 89 return false; 90 } 91 } 92 93 override bool opEquals(IObject o) { 94 return opEquals(cast(Object) o); 95 } 96 /** 97 * Returns the hash code value for this set. The hash code of a set is 98 * defined to be the sum of the hash codes of the elements in the set, 99 * where the hash code of a <tt>null</tt> element is defined to be zero. 100 * This ensures that <tt>s1.equals(s2)</tt> implies that 101 * <tt>s1.toHash()==s2.toHash()</tt> for any two sets <tt>s1</tt> 102 * and <tt>s2</tt>, as required by the general contract of 103 * {@link Object#hashCode}. 104 * 105 * <p>This implementation iterates over the set, calling the 106 * <tt>hashCode</tt> method on each element in the set, and adding up 107 * the results. 108 * 109 * @return the hash code value for this set 110 * @see Object#equals(Object) 111 * @see Set#equals(Object) 112 */ 113 override size_t toHash() @trusted nothrow { 114 try { 115 size_t h = 0; 116 foreach(E item; this) 117 h += hashOf(item); 118 return h; 119 } 120 catch(Exception) { 121 return 0; 122 } 123 } 124 125 override string toString() { 126 return super.toString(); 127 } 128 129 /** 130 * Removes from this set all of its elements that are contained in the 131 * specified collection (optional operation). If the specified 132 * collection is also a set, this operation effectively modifies this 133 * set so that its value is the <i>asymmetric set difference</i> of 134 * the two sets. 135 * 136 * <p>This implementation determines which is the smaller of this set 137 * and the specified collection, by invoking the <tt>size</tt> 138 * method on each. If this set has fewer elements, then the 139 * implementation iterates over this set, checking each element 140 * returned by the iterator in turn to see if it is contained in 141 * the specified collection. If it is so contained, it is removed 142 * from this set with the iterator's <tt>remove</tt> method. If 143 * the specified collection has fewer elements, then the 144 * implementation iterates over the specified collection, removing 145 * from this set each element returned by the iterator, using this 146 * set's <tt>remove</tt> method. 147 * 148 * <p>Note that this implementation will throw an 149 * <tt>UnsupportedOperationException</tt> if the iterator returned by the 150 * <tt>iterator</tt> method does not implement the <tt>remove</tt> method. 151 * 152 * @param c collection containing elements to be removed from this set 153 * @return <tt>true</tt> if this set changed as a result of the call 154 * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation 155 * is not supported by this set 156 * @throws ClassCastException if the class of an element of this set 157 * is incompatible with the specified collection 158 * (<a href="Collection.html#optional-restrictions">optional</a>) 159 * @throws NullPointerException if this set contains a null element and the 160 * specified collection does not permit null elements 161 * (<a href="Collection.html#optional-restrictions">optional</a>), 162 * or if the specified collection is null 163 * @see #remove(Object) 164 * @see #contains(Object) 165 */ 166 override bool removeAll(Collection!E c) { 167 assert(c !is null); 168 169 bool modified = false; 170 171 // throw new NotImplementedException(""); 172 173 if (size() > c.size()) { 174 foreach(E k; c) { 175 if(this.contains(k)) { 176 this.remove(k); modified = true; 177 } 178 } 179 // for (Iterator<?> i = c.iterator(); i.hasNext(); ) 180 // modified |= remove(i.next()); 181 } else { 182 // for (Iterator<?> i = iterator(); i.hasNext(); ) { 183 // if (c.contains(i.next())) { 184 // i.remove(); 185 // modified = true; 186 // } 187 // } 188 foreach(E k; this) { 189 if(c.contains(k)) { 190 this.remove(k); 191 modified = true; 192 } 193 } 194 195 } 196 return modified; 197 } 198 199 } 200 201 202 /** 203 */ 204 class EmptySet(E) : AbstractSet!(E) { 205 206 // Iterator!(E) iterator() { return emptyIterator(); } 207 208 override int size() {return 0;} 209 override bool isEmpty() {return true;} 210 override void clear() {} 211 212 override bool contains(E obj) {return false;} 213 override bool containsAll(Collection!E c) { return c.isEmpty(); } 214 215 override E[] toArray() { return []; } 216 217 // <T> T[] toArray(T[] a) { 218 // if (a.length > 0) 219 // a[0] = null; 220 // return a; 221 // } 222 223 // Override default methods in Collection 224 // override 225 // void forEach(Consumer<? super E> action) { 226 // Objects.requireNonNull(action); 227 // } 228 override bool removeIf(Predicate!E filter) { 229 assert(filter !is null); 230 return false; 231 } 232 233 override size_t toHash() @trusted nothrow { 234 return 0; 235 } 236 }