Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2009 The Guava Authors
      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 static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import com.google.common.annotations.GwtCompatible;
     22 import com.google.common.base.Preconditions;
     23 
     24 import java.util.List;
     25 import java.util.NoSuchElementException;
     26 
     27 import javax.annotation.Nullable;
     28 
     29 /**
     30  * Implementation of {@link ImmutableList} with exactly one element.
     31  *
     32  * @author Hayward Chan
     33  */
     34 @GwtCompatible(serializable = true, emulated = true)
     35 @SuppressWarnings("serial") // uses writeReplace(), not default serialization
     36 final class SingletonImmutableList<E> extends ImmutableList<E> {
     37 
     38   final transient E element;
     39 
     40   SingletonImmutableList(E element) {
     41     this.element = checkNotNull(element);
     42   }
     43 
     44   @Override
     45   public E get(int index) {
     46     Preconditions.checkElementIndex(index, 1);
     47     return element;
     48   }
     49 
     50   @Override public int indexOf(@Nullable Object object) {
     51     return element.equals(object) ? 0 : -1;
     52   }
     53 
     54   @Override public UnmodifiableIterator<E> iterator() {
     55     return Iterators.singletonIterator(element);
     56   }
     57 
     58   @Override public int lastIndexOf(@Nullable Object object) {
     59     return element.equals(object) ? 0 : -1;
     60   }
     61 
     62   @Override public UnmodifiableListIterator<E> listIterator(final int start) {
     63     Preconditions.checkPositionIndex(start, 1);
     64     return new UnmodifiableListIterator<E>() {
     65 
     66       boolean hasNext = start == 0;
     67 
     68       @Override public boolean hasNext() {
     69         return hasNext;
     70       }
     71 
     72       @Override public boolean hasPrevious() {
     73         return !hasNext;
     74       }
     75 
     76       @Override public E next() {
     77         if (!hasNext) {
     78           throw new NoSuchElementException();
     79         }
     80         hasNext = false;
     81         return element;
     82       }
     83 
     84       @Override public int nextIndex() {
     85         return hasNext ? 0 : 1;
     86       }
     87 
     88       @Override public E previous() {
     89         if (hasNext) {
     90           throw new NoSuchElementException();
     91         }
     92         hasNext = true;
     93         return element;
     94       }
     95 
     96       @Override public int previousIndex() {
     97         return hasNext ? -1 : 0;
     98       }
     99     };
    100   }
    101 
    102   @Override
    103   public int size() {
    104     return 1;
    105   }
    106 
    107   @Override public ImmutableList<E> subList(int fromIndex, int toIndex) {
    108     Preconditions.checkPositionIndexes(fromIndex, toIndex, 1);
    109     return (fromIndex == toIndex) ? ImmutableList.<E>of() : this;
    110   }
    111 
    112   @Override public ImmutableList<E> reverse() {
    113     return this;
    114   }
    115 
    116   @Override public boolean contains(@Nullable Object object) {
    117     return element.equals(object);
    118   }
    119 
    120   @Override public boolean equals(Object object) {
    121     if (object == this) {
    122       return true;
    123     }
    124     if (object instanceof List) {
    125       List<?> that = (List<?>) object;
    126       return that.size() == 1 && element.equals(that.get(0));
    127     }
    128     return false;
    129   }
    130 
    131   @Override public int hashCode() {
    132     // not caching hash code since it could change if the element is mutable
    133     // in a way that modifies its hash code.
    134     return 31 + element.hashCode();
    135   }
    136 
    137   @Override public String toString() {
    138     String elementToString = element.toString();
    139     return new StringBuilder(elementToString.length() + 2)
    140         .append('[')
    141         .append(elementToString)
    142         .append(']')
    143         .toString();
    144   }
    145 
    146   @Override public boolean isEmpty() {
    147     return false;
    148   }
    149 
    150   @Override boolean isPartialView() {
    151     return false;
    152   }
    153 
    154   @Override public Object[] toArray() {
    155     return new Object[] { element };
    156   }
    157 
    158   @Override public <T> T[] toArray(T[] array) {
    159     if (array.length == 0) {
    160       array = ObjectArrays.newArray(array, 1);
    161     } else if (array.length > 1) {
    162       array[1] = null;
    163     }
    164     // Writes will produce ArrayStoreException when the toArray() doc requires.
    165     Object[] objectArray = array;
    166     objectArray[0] = element;
    167     return array;
    168   }
    169 }
    170