• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.base.Preconditions;
21 
22 import java.util.Set;
23 
24 import javax.annotation.Nullable;
25 
26 /**
27  * Implementation of {@link ImmutableSet} with exactly one element.
28  *
29  * @author Kevin Bourrillion
30  * @author Nick Kralevich
31  */
32 @GwtCompatible(serializable = true)
33 @SuppressWarnings("serial") // uses writeReplace(), not default serialization
34 final class SingletonImmutableSet<E> extends ImmutableSet<E> {
35   final transient E element;
36 
37   // Non-volatile because:
38   //   - Integer is immutable and thus thread-safe;
39   //   - no problems if one thread overwrites the cachedHashCode from another.
40   private transient Integer cachedHashCode;
41 
SingletonImmutableSet(E element)42   SingletonImmutableSet(E element) {
43     this.element = Preconditions.checkNotNull(element);
44   }
45 
SingletonImmutableSet(E element, int hashCode)46   SingletonImmutableSet(E element, int hashCode) {
47     // Guaranteed to be non-null by the presence of the pre-computed hash code.
48     this.element = element;
49     cachedHashCode = hashCode;
50   }
51 
size()52   public int size() {
53     return 1;
54   }
55 
isEmpty()56   @Override public boolean isEmpty() {
57     return false;
58   }
59 
contains(Object target)60   @Override public boolean contains(Object target) {
61     return element.equals(target);
62   }
63 
iterator()64   @Override public UnmodifiableIterator<E> iterator() {
65     return Iterators.singletonIterator(element);
66   }
67 
toArray()68   @Override public Object[] toArray() {
69     return new Object[] { element };
70   }
71 
72   @SuppressWarnings({"unchecked"})
toArray(T[] array)73   @Override public <T> T[] toArray(T[] array) {
74     if (array.length == 0) {
75       array = ObjectArrays.newArray(array, 1);
76     } else if (array.length > 1) {
77       array[1] = null;
78     }
79     // Writes will produce ArrayStoreException when the toArray() doc requires.
80     Object[] objectArray = array;
81     objectArray[0] = element;
82     return array;
83   }
84 
equals(@ullable Object object)85   @Override public boolean equals(@Nullable Object object) {
86     if (object == this) {
87       return true;
88     }
89     if (object instanceof Set) {
90       Set<?> that = (Set<?>) object;
91       return that.size() == 1 && element.equals(that.iterator().next());
92     }
93     return false;
94   }
95 
hashCode()96   @Override public final int hashCode() {
97     Integer code = cachedHashCode;
98     if (code == null) {
99       return cachedHashCode = element.hashCode();
100     }
101     return code;
102   }
103 
isHashCodeFast()104   @Override boolean isHashCodeFast() {
105     return false;
106   }
107 
toString()108   @Override public String toString() {
109     String elementToString = element.toString();
110     return new StringBuilder(elementToString.length() + 2)
111         .append('[')
112         .append(elementToString)
113         .append(']')
114         .toString();
115   }
116 }
117