/* * Copyright (C) 2009 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; /** * GWT emulated version of {@link ImmutableSet}. For the unsorted sets, they * are thin wrapper around {@link java.util.Collections#emptySet()}, {@link * Collections#singleton(Object)} and {@link java.util.LinkedHashSet} for * empty, singleton and regular sets respectively. For the sorted sets, it's * a thin wrapper around {@link java.util.TreeSet}. * * @see ImmutableSortedSet * * @author Hayward Chan */ @SuppressWarnings("serial") // Serialization only done in GWT. public abstract class ImmutableSet extends ForwardingImmutableCollection implements Set { ImmutableSet(Set delegate) { super(Collections.unmodifiableSet(delegate)); } ImmutableSet() { this(Collections.emptySet()); } // Casting to any type is safe because the set will never hold any elements. @SuppressWarnings({"unchecked"}) public static ImmutableSet of() { return (ImmutableSet) EmptyImmutableSet.INSTANCE; } public static ImmutableSet of(E element) { return new SingletonImmutableSet(element); } @SuppressWarnings("unchecked") public static ImmutableSet of(E e1, E e2) { return create(e1, e2); } @SuppressWarnings("unchecked") public static ImmutableSet of(E e1, E e2, E e3) { return create(e1, e2, e3); } @SuppressWarnings("unchecked") public static ImmutableSet of(E e1, E e2, E e3, E e4) { return create(e1, e2, e3, e4); } @SuppressWarnings("unchecked") public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5) { return create(e1, e2, e3, e4, e5); } @SuppressWarnings("unchecked") public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { int size = others.length + 6; List all = new ArrayList(size); Collections.addAll(all, e1, e2, e3, e4, e5, e6); Collections.addAll(all, others); return copyOf(all.iterator()); } /** @deprecated */ @Deprecated public static ImmutableSet of(E[] elements) { return copyOf(elements); } public static ImmutableSet copyOf(E[] elements) { checkNotNull(elements); switch (elements.length) { case 0: return of(); case 1: return of(elements[0]); default: return create(elements); } } public static ImmutableSet copyOf(Collection elements) { Iterable iterable = elements; return copyOf(iterable); } public static ImmutableSet copyOf(Iterable elements) { if (elements instanceof ImmutableSet && !(elements instanceof ImmutableSortedSet)) { @SuppressWarnings("unchecked") // all supported methods are covariant ImmutableSet set = (ImmutableSet) elements; return set; } return copyOf(elements.iterator()); } public static ImmutableSet copyOf(Iterator elements) { if (!elements.hasNext()) { return of(); } E first = elements.next(); if (!elements.hasNext()) { // TODO: Remove "ImmutableSet." when eclipse bug is fixed. return ImmutableSet.of(first); } Set delegate = Sets.newLinkedHashSet(); delegate.add(checkNotNull(first)); do { delegate.add(checkNotNull(elements.next())); } while (elements.hasNext()); return unsafeDelegate(delegate); } // Factory methods that skips the null checks on elements, only used when // the elements are known to be non-null. static ImmutableSet unsafeDelegate(Set delegate) { switch (delegate.size()) { case 0: return of(); case 1: return new SingletonImmutableSet(delegate.iterator().next()); default: return new RegularImmutableSet(delegate); } } private static ImmutableSet create(E... elements) { // Create the set first, to remove duplicates if necessary. Set set = Sets.newLinkedHashSet(); Collections.addAll(set, elements); for (E element : set) { checkNotNull(element); } switch (set.size()) { case 0: return of(); case 1: return new SingletonImmutableSet(set.iterator().next()); default: return new RegularImmutableSet(set); } } @Override public boolean equals(Object obj) { return Sets.equalsImpl(this, obj); } @Override public int hashCode() { return delegate.hashCode(); } public static Builder builder() { return new Builder(); } public static class Builder extends ImmutableCollection.Builder { // accessed directly by ImmutableSortedSet final ArrayList contents = Lists.newArrayList(); public Builder() {} @Override public Builder add(E element) { contents.add(checkNotNull(element)); return this; } @Override public Builder add(E... elements) { checkNotNull(elements); // for GWT contents.ensureCapacity(contents.size() + elements.length); super.add(elements); return this; } @Override public Builder addAll(Iterable elements) { if (elements instanceof Collection) { Collection collection = (Collection) elements; contents.ensureCapacity(contents.size() + collection.size()); } super.addAll(elements); return this; } @Override public Builder addAll(Iterator elements) { super.addAll(elements); return this; } @Override public ImmutableSet build() { return copyOf(contents.iterator()); } } }