Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to you 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 org.apache.calcite.util; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * An immutable list that may contain null values. * * <p>If the list cannot contain null values, use * {@link com.google.common.collect.ImmutableList}.</p> * * @param <E> Element type */ public class ImmutableNullableList<E> extends AbstractList<E> { private static final List SINGLETON_NULL = Collections.singletonList(null); private final E[] elements; // private - does not copy array private ImmutableNullableList(E[] elements) { this.elements = elements; } /** * Returns an immutable list containing the given elements, in order. * * <p>Behavior as * {@link com.google.common.collect.ImmutableList#copyOf(java.util.Collection)} * except that this list allows nulls.</p> */ public static <E> List<E> copyOf(Collection<? extends E> elements) { if (elements instanceof ImmutableNullableList || elements instanceof ImmutableList || elements == SINGLETON_NULL) { //noinspection unchecked return (List<E>) elements; } // If there are no nulls, ImmutableList is better. for (E object : elements) { if (object == null) { final Object[] objects = elements.toArray(); //noinspection unchecked return new ImmutableNullableList<E>((E[]) objects); } } return ImmutableList.copyOf(elements); } /** * Returns an immutable list containing the given elements, in order. * * <p>Behavior as * {@link com.google.common.collect.ImmutableList#copyOf(Iterable)} * except that this list allows nulls. */ public static <E> List<E> copyOf(Iterable<? extends E> elements) { if (elements instanceof ImmutableNullableList || elements instanceof ImmutableList || elements == SINGLETON_NULL) { //noinspection unchecked return (List<E>) elements; } if (elements instanceof Collection) { //noinspection unchecked return copyOf((Collection) elements); } // If there are no nulls, ImmutableList is better. final List<E> list = new ArrayList<>(); Iterables.addAll(list, elements); if (list.contains(null)) { return ImmutableNullableList.copyOf(list); } return ImmutableList.copyOf(elements); } /** * Returns an immutable list containing the given elements, in order. * * <p>Behavior as * {@link com.google.common.collect.ImmutableList#copyOf(Object[])} * except that this list allows nulls.</p> */ public static <E> List<E> copyOf(E[] elements) { // Check for nulls. for (E object : elements) { if (object == null) { //noinspection unchecked return new ImmutableNullableList<E>(elements.clone()); } } // There are no nulls. ImmutableList is better. return ImmutableList.copyOf(elements); } /** Creates an immutable list of 1 element. */ public static <E> List<E> of(E e1) { //noinspection unchecked return e1 == null ? (List<E>) SINGLETON_NULL : ImmutableList.of(e1); } /** Creates an immutable list of 2 elements. */ public static <E> List<E> of(E e1, E e2) { // Only we can see the varargs array. Therefore the list is immutable. //noinspection unchecked return UnmodifiableArrayList.of(e1, e2); } /** Creates an immutable list of 3 elements. */ public static <E> List<E> of(E e1, E e2, E e3) { // Only we can see the varargs array. Therefore the list is immutable. //noinspection unchecked return UnmodifiableArrayList.of(e1, e2, e3); } /** Creates an immutable list of 4 elements. */ public static <E> List<E> of(E e1, E e2, E e3, E e4) { // Only we can see the varargs array. Therefore the list is immutable. //noinspection unchecked return UnmodifiableArrayList.of(e1, e2, e3, e4); } /** Creates an immutable list of 5 elements. */ public static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) { // Only we can see the varargs array. Therefore the list is immutable. //noinspection unchecked return UnmodifiableArrayList.of(e1, e2, e3, e4, e5); } /** Creates an immutable list of 6 elements. */ public static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { // Only we can see the varargs array. Therefore the list is immutable. //noinspection unchecked return UnmodifiableArrayList.of(e1, e2, e3, e4, e5, e6); } /** Creates an immutable list of 7 elements. */ public static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { // Only we can see the varargs array. Therefore the list is immutable. //noinspection unchecked return UnmodifiableArrayList.of(e1, e2, e3, e4, e5, e6, e7); } /** Creates an immutable list of 8 or more elements. */ public static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E... others) { Object[] array = new Object[8 + others.length]; array[0] = e1; array[1] = e2; array[2] = e3; array[3] = e4; array[4] = e5; array[5] = e6; array[6] = e7; array[7] = e8; System.arraycopy(others, 0, array, 8, others.length); //noinspection unchecked return new ImmutableNullableList<E>((E[]) array); } @Override public E get(int index) { return elements[index]; } @Override public int size() { return elements.length; } /** * Returns a new builder. The generated builder is equivalent to the builder * created by the {@link Builder} constructor. */ public static <E> Builder<E> builder() { return new Builder<E>(); } /** * A builder for creating immutable nullable list instances. */ public static final class Builder<E> { private final List<E> contents = Lists.newArrayList(); /** * Creates a new builder. The returned builder is equivalent to the builder * generated by * {@link org.apache.calcite.util.ImmutableNullableList#builder}. */ public Builder() { } /** * Adds {@code element} to the {@code ImmutableNullableList}. * * @param element the element to add * @return this {@code Builder} object */ public Builder<E> add(E element) { contents.add(element); return this; } /** * Adds each element of {@code elements} to the * {@code ImmutableNullableList}. * * @param elements the {@code Iterable} to add to the * {@code ImmutableNullableList} * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is null */ public Builder<E> addAll(Iterable<? extends E> elements) { Iterables.addAll(contents, elements); return this; } /** * Adds each element of {@code elements} to the * {@code ImmutableNullableList}. * * @param elements the elements to add to the {@code ImmutableNullableList} * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is null */ public Builder<E> add(E... elements) { for (E element : elements) { add(element); } return this; } /** * Adds each element of {@code elements} to the * {@code ImmutableNullableList}. * * @param elements the elements to add to the {@code ImmutableNullableList} * @return this {@code Builder} object * @throws NullPointerException if {@code elements} is null */ public Builder<E> addAll(Iterator<? extends E> elements) { Iterators.addAll(contents, elements); return this; } /** * Returns a newly-created {@code ImmutableNullableList} based on the * contents of the {@code Builder}. */ public List<E> build() { return copyOf(contents); } } } // End ImmutableNullableList.java