001 /* 002 * Copyright (C) 2007 Google Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package com.google.common.collect; 018 019 import static com.google.common.base.Preconditions.checkNotNull; 020 021 import com.google.common.annotations.GwtCompatible; 022 023 import java.io.Serializable; 024 import java.util.ArrayList; 025 import java.util.Arrays; 026 import java.util.Collection; 027 import java.util.Collections; 028 import java.util.HashSet; 029 import java.util.Iterator; 030 import java.util.List; 031 import java.util.Set; 032 033 import javax.annotation.Nullable; 034 035 /** 036 * A high-performance, immutable {@code Set} with reliable, user-specified 037 * iteration order. Does not permit null elements. 038 * 039 * <p>Unlike {@link Collections#unmodifiableSet}, which is a <i>view</i> of a 040 * separate collection that can still change, an instance of this class contains 041 * its own private data and will <i>never</i> change. This class is convenient 042 * for {@code public static final} sets ("constant sets") and also lets you 043 * easily make a "defensive copy" of a set provided to your class by a caller. 044 * 045 * <p><b>Warning:</b> Like most sets, an {@code ImmutableSet} will not function 046 * correctly if an element is modified after being placed in the set. For this 047 * reason, and to avoid general confusion, it is strongly recommended to place 048 * only immutable objects into this collection. 049 * 050 * <p>This class has been observed to perform significantly better than {@link 051 * HashSet} for objects with very fast {@link Object#hashCode} implementations 052 * (as a well-behaved immutable object should). While this class's factory 053 * methods create hash-based instances, the {@link ImmutableSortedSet} subclass 054 * performs binary searches instead. 055 * 056 * <p><b>Note</b>: Although this class is not final, it cannot be subclassed 057 * outside its package as it has no public or protected constructors. Thus, 058 * instances of this type are guaranteed to be immutable. 059 * 060 * @see ImmutableList 061 * @see ImmutableMap 062 * @author Kevin Bourrillion 063 * @author Nick Kralevich 064 * @since 2 (imported from Google Collections Library) 065 */ 066 // TODO: benchmark and optimize all creation paths, which are a mess right now 067 @GwtCompatible(serializable = true, emulated = true) 068 @SuppressWarnings("serial") // we're overriding default serialization 069 public abstract class ImmutableSet<E> extends ImmutableCollection<E> 070 implements Set<E> { 071 /** 072 * Returns the empty immutable set. This set behaves and performs comparably 073 * to {@link Collections#emptySet}, and is preferable mainly for consistency 074 * and maintainability of your code. 075 */ 076 // Casting to any type is safe because the set will never hold any elements. 077 @SuppressWarnings({"unchecked"}) 078 public static <E> ImmutableSet<E> of() { 079 return (ImmutableSet<E>) EmptyImmutableSet.INSTANCE; 080 } 081 082 /** 083 * Returns an immutable set containing a single element. This set behaves and 084 * performs comparably to {@link Collections#singleton}, but will not accept 085 * a null element. It is preferable mainly for consistency and 086 * maintainability of your code. 087 */ 088 public static <E> ImmutableSet<E> of(E element) { 089 return new SingletonImmutableSet<E>(element); 090 } 091 092 /** 093 * Returns an immutable set containing the given elements, in order. Repeated 094 * occurrences of an element (according to {@link Object#equals}) after the 095 * first are ignored. 096 * 097 * @throws NullPointerException if any element is null 098 */ 099 @SuppressWarnings("unchecked") 100 public static <E> ImmutableSet<E> of(E e1, E e2) { 101 return create(e1, e2); 102 } 103 104 /** 105 * Returns an immutable set containing the given elements, in order. Repeated 106 * occurrences of an element (according to {@link Object#equals}) after the 107 * first are ignored. 108 * 109 * @throws NullPointerException if any element is null 110 */ 111 @SuppressWarnings("unchecked") 112 public static <E> ImmutableSet<E> of(E e1, E e2, E e3) { 113 return create(e1, e2, e3); 114 } 115 116 /** 117 * Returns an immutable set containing the given elements, in order. Repeated 118 * occurrences of an element (according to {@link Object#equals}) after the 119 * first are ignored. 120 * 121 * @throws NullPointerException if any element is null 122 */ 123 @SuppressWarnings("unchecked") 124 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) { 125 return create(e1, e2, e3, e4); 126 } 127 128 /** 129 * Returns an immutable set containing the given elements, in order. Repeated 130 * occurrences of an element (according to {@link Object#equals}) after the 131 * first are ignored. 132 * 133 * @throws NullPointerException if any element is null 134 */ 135 @SuppressWarnings("unchecked") 136 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) { 137 return create(e1, e2, e3, e4, e5); 138 } 139 140 /** 141 * Returns an immutable set containing the given elements, in order. Repeated 142 * occurrences of an element (according to {@link Object#equals}) after the 143 * first are ignored. 144 * 145 * @throws NullPointerException if any element is null 146 * @since 3 (source-compatible since release 2) 147 */ 148 @SuppressWarnings("unchecked") 149 public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, 150 E... others) { 151 int size = others.length + 6; 152 List<E> all = new ArrayList<E>(size); 153 Collections.addAll(all, e1, e2, e3, e4, e5, e6); 154 Collections.addAll(all, others); 155 return create(all, size); 156 } 157 158 /** 159 * Returns an immutable set containing the given elements, in order. Repeated 160 * occurrences of an element (according to {@link Object#equals}) after the 161 * first are ignored. 162 * 163 * @deprecated use {@link #copyOf(Object[])}. 164 * @throws NullPointerException if any of {@code elements} is null 165 * @since 2 (changed from varargs in release 3) 166 */ 167 // TODO: when this is removed, remember to remove from ISS and ISSFS too 168 @Deprecated 169 public static <E> ImmutableSet<E> of(E[] elements) { 170 return copyOf(elements); 171 } 172 173 /** 174 * Returns an immutable set containing the given elements, in order. Repeated 175 * occurrences of an element (according to {@link Object#equals}) after the 176 * first are ignored. 177 * 178 * @throws NullPointerException if any of {@code elements} is null 179 * @since 3 180 */ 181 public static <E> ImmutableSet<E> copyOf(E[] elements) { 182 switch (elements.length) { 183 case 0: 184 return of(); 185 case 1: 186 return of(elements[0]); 187 default: 188 return create(elements); 189 } 190 } 191 192 /** 193 * Returns an immutable set containing the given elements, in order. Repeated 194 * occurrences of an element (according to {@link Object#equals}) after the 195 * first are ignored. This method iterates over {@code elements} at most 196 * once. 197 * 198 * <p>Note that if {@code s} is a {@code Set<String>}, then {@code 199 * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing 200 * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns 201 * a {@code ImmutableSet<Set<String>>} containing one element (the given set 202 * itself). 203 * 204 * <p><b>Note:</b> Despite what the method name suggests, if {@code elements} 205 * is an {@code ImmutableSet} (but not an {@code ImmutableSortedSet}), no copy 206 * will actually be performed, and the given set itself will be returned. 207 * 208 * @throws NullPointerException if any of {@code elements} is null 209 */ 210 public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) { 211 if (elements instanceof ImmutableSet 212 && !(elements instanceof ImmutableSortedSet)) { 213 @SuppressWarnings("unchecked") // all supported methods are covariant 214 ImmutableSet<E> set = (ImmutableSet<E>) elements; 215 return set; 216 } 217 return copyOfInternal(Collections2.toCollection(elements)); 218 } 219 220 /** 221 * Returns an immutable set containing the given elements, in order. Repeated 222 * occurrences of an element (according to {@link Object#equals}) after the 223 * first are ignored. 224 * 225 * @throws NullPointerException if any of {@code elements} is null 226 */ 227 public static <E> ImmutableSet<E> copyOf(Iterator<? extends E> elements) { 228 Collection<E> list = Lists.newArrayList(elements); 229 return copyOfInternal(list); 230 } 231 232 private static <E> ImmutableSet<E> copyOfInternal( 233 Collection<? extends E> collection) { 234 // TODO: Support concurrent collections that change while this method is 235 // running. 236 switch (collection.size()) { 237 case 0: 238 return of(); 239 case 1: 240 // TODO: Remove "ImmutableSet.<E>" when eclipse bug is fixed. 241 return ImmutableSet.<E>of(collection.iterator().next()); 242 default: 243 return create(collection, collection.size()); 244 } 245 } 246 247 ImmutableSet() {} 248 249 /** Returns {@code true} if the {@code hashCode()} method runs quickly. */ 250 boolean isHashCodeFast() { 251 return false; 252 } 253 254 @Override public boolean equals(@Nullable Object object) { 255 if (object == this) { 256 return true; 257 } 258 if (object instanceof ImmutableSet 259 && isHashCodeFast() 260 && ((ImmutableSet<?>) object).isHashCodeFast() 261 && hashCode() != object.hashCode()) { 262 return false; 263 } 264 return Collections2.setEquals(this, object); 265 } 266 267 @Override public int hashCode() { 268 int hashCode = 0; 269 for (Object o : this) { 270 hashCode += o.hashCode(); 271 } 272 return hashCode; 273 } 274 275 // This declaration is needed to make Set.iterator() and 276 // ImmutableCollection.iterator() consistent. 277 @Override public abstract UnmodifiableIterator<E> iterator(); 278 279 private static <E> ImmutableSet<E> create(E... elements) { 280 return create(Arrays.asList(elements), elements.length); 281 } 282 283 private static <E> ImmutableSet<E> create( 284 Iterable<? extends E> iterable, int count) { 285 // count is always the (nonzero) number of elements in the iterable 286 int tableSize = Hashing.chooseTableSize(count); 287 Object[] table = new Object[tableSize]; 288 int mask = tableSize - 1; 289 290 List<E> elements = new ArrayList<E>(count); 291 int hashCode = 0; 292 293 for (E element : iterable) { 294 int hash = element.hashCode(); 295 for (int i = Hashing.smear(hash); true; i++) { 296 int index = i & mask; 297 Object value = table[index]; 298 if (value == null) { 299 // Came to an empty bucket. Put the element here. 300 table[index] = element; 301 elements.add(element); 302 hashCode += hash; 303 break; 304 } else if (value.equals(element)) { 305 break; // Found a duplicate. Nothing to do. 306 } 307 } 308 } 309 310 if (elements.size() == 1) { 311 // The iterable contained only duplicates of the same element. 312 return new SingletonImmutableSet<E>(elements.get(0), hashCode); 313 } else if (tableSize > Hashing.chooseTableSize(elements.size())) { 314 // Resize the table when the iterable includes too many duplicates. 315 return create(elements, elements.size()); 316 } else { 317 return new RegularImmutableSet<E>( 318 elements.toArray(), hashCode, table, mask); 319 } 320 } 321 322 abstract static class ArrayImmutableSet<E> extends ImmutableSet<E> { 323 // the elements (two or more) in the desired order. 324 final transient Object[] elements; 325 326 ArrayImmutableSet(Object[] elements) { 327 this.elements = elements; 328 } 329 330 public int size() { 331 return elements.length; 332 } 333 334 @Override public boolean isEmpty() { 335 return false; 336 } 337 338 /* 339 * The cast is safe because the only way to create an instance is via the 340 * create() method above, which only permits elements of type E. 341 */ 342 @SuppressWarnings("unchecked") 343 @Override public UnmodifiableIterator<E> iterator() { 344 return (UnmodifiableIterator<E>) Iterators.forArray(elements); 345 } 346 347 @Override public Object[] toArray() { 348 Object[] array = new Object[size()]; 349 System.arraycopy(elements, 0, array, 0, size()); 350 return array; 351 } 352 353 @Override public <T> T[] toArray(T[] array) { 354 int size = size(); 355 if (array.length < size) { 356 array = ObjectArrays.newArray(array, size); 357 } else if (array.length > size) { 358 array[size] = null; 359 } 360 System.arraycopy(elements, 0, array, 0, size); 361 return array; 362 } 363 364 @Override public boolean containsAll(Collection<?> targets) { 365 if (targets == this) { 366 return true; 367 } 368 if (!(targets instanceof ArrayImmutableSet)) { 369 return super.containsAll(targets); 370 } 371 if (targets.size() > size()) { 372 return false; 373 } 374 for (Object target : ((ArrayImmutableSet<?>) targets).elements) { 375 if (!contains(target)) { 376 return false; 377 } 378 } 379 return true; 380 } 381 382 @Override ImmutableList<E> createAsList() { 383 return new ImmutableAsList<E>(elements, this); 384 } 385 } 386 387 /** such as ImmutableMap.keySet() */ 388 abstract static class TransformedImmutableSet<D, E> extends ImmutableSet<E> { 389 final D[] source; 390 final int hashCode; 391 392 TransformedImmutableSet(D[] source, int hashCode) { 393 this.source = source; 394 this.hashCode = hashCode; 395 } 396 397 abstract E transform(D element); 398 399 public int size() { 400 return source.length; 401 } 402 403 @Override public boolean isEmpty() { 404 return false; 405 } 406 407 @Override public UnmodifiableIterator<E> iterator() { 408 return new AbstractIterator<E>() { 409 int index = 0; 410 @Override protected E computeNext() { 411 return index < source.length 412 ? transform(source[index++]) 413 : endOfData(); 414 } 415 }; 416 } 417 418 @Override public Object[] toArray() { 419 return toArray(new Object[size()]); 420 } 421 422 @Override public <T> T[] toArray(T[] array) { 423 int size = size(); 424 if (array.length < size) { 425 array = ObjectArrays.newArray(array, size); 426 } else if (array.length > size) { 427 array[size] = null; 428 } 429 430 // Writes will produce ArrayStoreException when the toArray() doc requires 431 Object[] objectArray = array; 432 for (int i = 0; i < source.length; i++) { 433 objectArray[i] = transform(source[i]); 434 } 435 return array; 436 } 437 438 @Override public final int hashCode() { 439 return hashCode; 440 } 441 442 @Override boolean isHashCodeFast() { 443 return true; 444 } 445 } 446 447 /* 448 * This class is used to serialize all ImmutableSet instances, except for 449 * ImmutableEnumSet/ImmutableSortedSet, regardless of implementation type. It 450 * captures their "logical contents" and they are reconstructed using public 451 * static factories. This is necessary to ensure that the existence of a 452 * particular implementation type is an implementation detail. 453 */ 454 private static class SerializedForm implements Serializable { 455 final Object[] elements; 456 SerializedForm(Object[] elements) { 457 this.elements = elements; 458 } 459 Object readResolve() { 460 return copyOf(elements); 461 } 462 private static final long serialVersionUID = 0; 463 } 464 465 @Override Object writeReplace() { 466 return new SerializedForm(toArray()); 467 } 468 469 /** 470 * Returns a new builder. The generated builder is equivalent to the builder 471 * created by the {@link Builder} constructor. 472 */ 473 public static <E> Builder<E> builder() { 474 return new Builder<E>(); 475 } 476 477 /** 478 * A builder for creating immutable set instances, especially 479 * {@code public static final} sets ("constant sets"). 480 * 481 * <p>Example: 482 * <pre>{@code 483 * public static final ImmutableSet<Color> GOOGLE_COLORS 484 * = new ImmutableSet.Builder<Color>() 485 * .addAll(WEBSAFE_COLORS) 486 * .add(new Color(0, 191, 255)) 487 * .build();}</pre> 488 * 489 * <p>Builder instances can be reused - it is safe to call {@link #build} 490 * multiple times to build multiple sets in series. Each set 491 * is a superset of the set created before it. 492 */ 493 public static class Builder<E> extends ImmutableCollection.Builder<E> { 494 // accessed directly by ImmutableSortedSet 495 final ArrayList<E> contents = Lists.newArrayList(); 496 497 /** 498 * Creates a new builder. The returned builder is equivalent to the builder 499 * generated by {@link ImmutableSet#builder}. 500 */ 501 public Builder() {} 502 503 /** 504 * Adds {@code element} to the {@code ImmutableSet}. If the {@code 505 * ImmutableSet} already contains {@code element}, then {@code add} has no 506 * effect (only the previously added element is retained). 507 * 508 * @param element the element to add 509 * @return this {@code Builder} object 510 * @throws NullPointerException if {@code element} is null 511 */ 512 @Override public Builder<E> add(E element) { 513 contents.add(checkNotNull(element)); 514 return this; 515 } 516 517 /** 518 * Adds each element of {@code elements} to the {@code ImmutableSet}, 519 * ignoring duplicate elements (only the first duplicate element is added). 520 * 521 * @param elements the elements to add 522 * @return this {@code Builder} object 523 * @throws NullPointerException if {@code elements} is null or contains a 524 * null element 525 */ 526 @Override public Builder<E> add(E... elements) { 527 contents.ensureCapacity(contents.size() + elements.length); 528 super.add(elements); 529 return this; 530 } 531 532 /** 533 * Adds each element of {@code elements} to the {@code ImmutableSet}, 534 * ignoring duplicate elements (only the first duplicate element is added). 535 * 536 * @param elements the {@code Iterable} to add to the {@code ImmutableSet} 537 * @return this {@code Builder} object 538 * @throws NullPointerException if {@code elements} is null or contains a 539 * null element 540 */ 541 @Override public Builder<E> addAll(Iterable<? extends E> elements) { 542 if (elements instanceof Collection) { 543 Collection<?> collection = (Collection<?>) elements; 544 contents.ensureCapacity(contents.size() + collection.size()); 545 } 546 super.addAll(elements); 547 return this; 548 } 549 550 /** 551 * Adds each element of {@code elements} to the {@code ImmutableSet}, 552 * ignoring duplicate elements (only the first duplicate element is added). 553 * 554 * @param elements the elements to add to the {@code ImmutableSet} 555 * @return this {@code Builder} object 556 * @throws NullPointerException if {@code elements} is null or contains a 557 * null element 558 */ 559 @Override public Builder<E> addAll(Iterator<? extends E> elements) { 560 super.addAll(elements); 561 return this; 562 } 563 564 /** 565 * Returns a newly-created {@code ImmutableSet} based on the contents of 566 * the {@code Builder}. 567 */ 568 @Override public ImmutableSet<E> build() { 569 return copyOf(contents); 570 } 571 } 572 }