/*
* Copyright (C) 2007 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.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndex;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.math.IntMath;
import com.google.common.primitives.Ints;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Serializable;
import java.math.RoundingMode;
import java.util.AbstractList;
import java.util.AbstractSequentialList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.RandomAccess;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import org.checkerframework.checker.nullness.qual.Nullable;
Static utility methods pertaining to List
instances. Also see this class's counterparts Sets
, Maps
and Queues
. See the Guava User Guide article on Lists
.
Author: Kevin Bourrillion, Mike Bostock, Louis Wasserman Since: 2.0
/**
* Static utility methods pertaining to {@link List} instances. Also see this class's counterparts
* {@link Sets}, {@link Maps} and {@link Queues}.
*
* <p>See the Guava User Guide article on <a href=
* "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#lists"> {@code Lists}</a>.
*
* @author Kevin Bourrillion
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0
*/
@GwtCompatible(emulated = true)
public final class Lists {
private Lists() {}
// ArrayList
Creates a mutable, empty ArrayList
instance (for Java 6 and earlier). Note: if mutability is not required, use ImmutableList.of()
instead.
Note for Java 7 and later: this method is now unnecessary and should be treated as deprecated. Instead, use the ArrayList
constructor directly, taking advantage of the new "diamond" syntax.
/**
* Creates a <i>mutable</i>, empty {@code ArrayList} instance (for Java 6 and earlier).
*
* <p><b>Note:</b> if mutability is not required, use {@link ImmutableList#of()} instead.
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use the {@code ArrayList} {@linkplain ArrayList#ArrayList() constructor}
* directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*/
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList() {
return new ArrayList<>();
}
Creates a mutable ArrayList
instance containing the given elements. Note: essentially the only reason to use this method is when you will need to add or remove elements later. Otherwise, for non-null elements use ImmutableList.of()
(for varargs) or ImmutableList.copyOf(Object[])
(for an array) instead. If any elements might be null, or you need support for List.set(int, Object)
, use Arrays.asList
.
Note that even when you do need the ability to add or remove, this method provides only a tiny bit of syntactic sugar for newArrayList(
asList
(...))
, or for creating an empty list then calling Collections.addAll
. This method is not actually very useful and will likely be deprecated in the future.
/**
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements.
*
* <p><b>Note:</b> essentially the only reason to use this method is when you will need to add or
* remove elements later. Otherwise, for non-null elements use {@link ImmutableList#of()} (for
* varargs) or {@link ImmutableList#copyOf(Object[])} (for an array) instead. If any elements
* might be null, or you need support for {@link List#set(int, Object)}, use {@link
* Arrays#asList}.
*
* <p>Note that even when you do need the ability to add or remove, this method provides only a
* tiny bit of syntactic sugar for {@code newArrayList(}{@link Arrays#asList asList}{@code
* (...))}, or for creating an empty list then calling {@link Collections#addAll}. This method is
* not actually very useful and will likely be deprecated in the future.
*/
@SafeVarargs
@CanIgnoreReturnValue // TODO(kak): Remove this
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList(E... elements) {
checkNotNull(elements); // for GWT
// Avoid integer overflow when a large array is passed in
int capacity = computeArrayListCapacity(elements.length);
ArrayList<E> list = new ArrayList<>(capacity);
Collections.addAll(list, elements);
return list;
}
Creates a mutable ArrayList
instance containing the given elements; a very thin shortcut for creating an empty list then calling Iterables.addAll
. Note: if mutability is not required and the elements are non-null, use ImmutableList.copyOf(Iterable<? extends Object>)
instead. (Or, change elements
to be a FluentIterable
and call elements.toList()
.)
Note for Java 7 and later: if elements
is a Collection
, you don't need this method. Use the ArrayList
constructor directly, taking advantage of the new "diamond"
syntax.
/**
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements; a very thin
* shortcut for creating an empty list then calling {@link Iterables#addAll}.
*
* <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
* ImmutableList#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
* FluentIterable} and call {@code elements.toList()}.)
*
* <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
* need this method. Use the {@code ArrayList} {@linkplain ArrayList#ArrayList(Collection)
* constructor} directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond"
* syntax</a>.
*/
@CanIgnoreReturnValue // TODO(kak): Remove this
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
checkNotNull(elements); // for GWT
// Let ArrayList's sizing logic work, if possible
return (elements instanceof Collection)
? new ArrayList<>(Collections2.cast(elements))
: newArrayList(elements.iterator());
}
Creates a mutable ArrayList
instance containing the given elements; a very thin shortcut for creating an empty list and then calling Iterators.addAll
. Note: if mutability is not required and the elements are non-null, use ImmutableList.copyOf(Iterator<? extends Object>)
instead.
/**
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements; a very thin
* shortcut for creating an empty list and then calling {@link Iterators#addAll}.
*
* <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
* ImmutableList#copyOf(Iterator)} instead.
*/
@CanIgnoreReturnValue // TODO(kak): Remove this
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
ArrayList<E> list = newArrayList();
Iterators.addAll(list, elements);
return list;
}
@VisibleForTesting
static int computeArrayListCapacity(int arraySize) {
checkNonnegative(arraySize, "arraySize");
// TODO(kevinb): Figure out the right behavior, and document it
return Ints.saturatedCast(5L + arraySize + (arraySize / 10));
}
Creates an ArrayList
instance backed by an array with the specified initial size; simply delegates to ArrayList(int)
. Note for Java 7 and later: this method is now unnecessary and should be treated as deprecated. Instead, use new
ArrayList
<>(int)
directly, taking advantage of the new "diamond" syntax. (Unlike here, there is no risk of overload ambiguity, since the ArrayList
constructors very wisely did not accept varargs.)
Params: - initialArraySize – the exact size of the initial backing array for the returned array list (
ArrayList
documentation calls this value the "capacity")
Throws: - IllegalArgumentException – if
initialArraySize
is negative
Returns: a new, empty ArrayList
which is guaranteed not to resize itself unless its size reaches initialArraySize + 1
/**
* Creates an {@code ArrayList} instance backed by an array with the specified initial size;
* simply delegates to {@link ArrayList#ArrayList(int)}.
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use {@code new }{@link ArrayList#ArrayList(int) ArrayList}{@code <>(int)}
* directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
* (Unlike here, there is no risk of overload ambiguity, since the {@code ArrayList} constructors
* very wisely did not accept varargs.)
*
* @param initialArraySize the exact size of the initial backing array for the returned array list
* ({@code ArrayList} documentation calls this value the "capacity")
* @return a new, empty {@code ArrayList} which is guaranteed not to resize itself unless its size
* reaches {@code initialArraySize + 1}
* @throws IllegalArgumentException if {@code initialArraySize} is negative
*/
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.
return new ArrayList<>(initialArraySize);
}
Creates an ArrayList
instance to hold estimatedSize
elements, plus an unspecified amount of padding; you almost certainly mean to call newArrayListWithCapacity
(see that method for further advice on usage). Note: This method will soon be deprecated. Even in the rare case that you do want
some amount of padding, it's best if you choose your desired amount explicitly.
Params: - estimatedSize – an estimate of the eventual
List.size()
of the new list
Throws: - IllegalArgumentException – if
estimatedSize
is negative
Returns: a new, empty ArrayList
, sized appropriately to hold the estimated number of elements
/**
* Creates an {@code ArrayList} instance to hold {@code estimatedSize} elements, <i>plus</i> an
* unspecified amount of padding; you almost certainly mean to call {@link
* #newArrayListWithCapacity} (see that method for further advice on usage).
*
* <p><b>Note:</b> This method will soon be deprecated. Even in the rare case that you do want
* some amount of padding, it's best if you choose your desired amount explicitly.
*
* @param estimatedSize an estimate of the eventual {@link List#size()} of the new list
* @return a new, empty {@code ArrayList}, sized appropriately to hold the estimated number of
* elements
* @throws IllegalArgumentException if {@code estimatedSize} is negative
*/
@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
return new ArrayList<>(computeArrayListCapacity(estimatedSize));
}
// LinkedList
Creates a mutable, empty LinkedList
instance (for Java 6 and earlier). Note: if you won't be adding any elements to the list, use ImmutableList.of()
instead.
Performance note: ArrayList
and ArrayDeque
consistently outperform LinkedList
except in certain rare and specific situations. Unless you have spent a lot of time benchmarking your specific needs, use one of those instead.
Note for Java 7 and later: this method is now unnecessary and should be treated as deprecated. Instead, use the LinkedList
constructor directly, taking advantage of the new "diamond"
syntax.
/**
* Creates a <i>mutable</i>, empty {@code LinkedList} instance (for Java 6 and earlier).
*
* <p><b>Note:</b> if you won't be adding any elements to the list, use {@link ImmutableList#of()}
* instead.
*
* <p><b>Performance note:</b> {@link ArrayList} and {@link java.util.ArrayDeque} consistently
* outperform {@code LinkedList} except in certain rare and specific situations. Unless you have
* spent a lot of time benchmarking your specific needs, use one of those instead.
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use the {@code LinkedList} {@linkplain LinkedList#LinkedList()
* constructor} directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond"
* syntax</a>.
*/
@GwtCompatible(serializable = true)
public static <E> LinkedList<E> newLinkedList() {
return new LinkedList<>();
}
Creates a mutable LinkedList
instance containing the given elements; a very thin shortcut for creating an empty list then calling Iterables.addAll
. Note: if mutability is not required and the elements are non-null, use ImmutableList.copyOf(Iterable<? extends Object>)
instead. (Or, change elements
to be a FluentIterable
and call elements.toList()
.)
Performance note: ArrayList
and ArrayDeque
consistently outperform LinkedList
except in certain rare and specific situations. Unless you have spent a lot of time benchmarking your specific needs, use one of those instead.
Note for Java 7 and later: if elements
is a Collection
, you don't need this method. Use the LinkedList
constructor directly, taking advantage of the new "diamond"
syntax.
/**
* Creates a <i>mutable</i> {@code LinkedList} instance containing the given elements; a very thin
* shortcut for creating an empty list then calling {@link Iterables#addAll}.
*
* <p><b>Note:</b> if mutability is not required and the elements are non-null, use {@link
* ImmutableList#copyOf(Iterable)} instead. (Or, change {@code elements} to be a {@link
* FluentIterable} and call {@code elements.toList()}.)
*
* <p><b>Performance note:</b> {@link ArrayList} and {@link java.util.ArrayDeque} consistently
* outperform {@code LinkedList} except in certain rare and specific situations. Unless you have
* spent a lot of time benchmarking your specific needs, use one of those instead.
*
* <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
* need this method. Use the {@code LinkedList} {@linkplain LinkedList#LinkedList(Collection)
* constructor} directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond"
* syntax</a>.
*/
@GwtCompatible(serializable = true)
public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
LinkedList<E> list = newLinkedList();
Iterables.addAll(list, elements);
return list;
}
Creates an empty CopyOnWriteArrayList
instance. Note: if you need an immutable empty List
, use Collections.emptyList
instead.
Returns: a new, empty CopyOnWriteArrayList
Since: 12.0
/**
* Creates an empty {@code CopyOnWriteArrayList} instance.
*
* <p><b>Note:</b> if you need an immutable empty {@link List}, use {@link Collections#emptyList}
* instead.
*
* @return a new, empty {@code CopyOnWriteArrayList}
* @since 12.0
*/
@GwtIncompatible // CopyOnWriteArrayList
public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList() {
return new CopyOnWriteArrayList<>();
}
Creates a CopyOnWriteArrayList
instance containing the given elements. Params: - elements – the elements that the list should contain, in order
Returns: a new CopyOnWriteArrayList
containing those elements Since: 12.0
/**
* Creates a {@code CopyOnWriteArrayList} instance containing the given elements.
*
* @param elements the elements that the list should contain, in order
* @return a new {@code CopyOnWriteArrayList} containing those elements
* @since 12.0
*/
@GwtIncompatible // CopyOnWriteArrayList
public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList(
Iterable<? extends E> elements) {
// We copy elements to an ArrayList first, rather than incurring the
// quadratic cost of adding them to the COWAL directly.
Collection<? extends E> elementsCollection =
(elements instanceof Collection) ? Collections2.cast(elements) : newArrayList(elements);
return new CopyOnWriteArrayList<>(elementsCollection);
}
Returns an unmodifiable list containing the specified first element and backed by the specified array of additional elements. Changes to the rest
array will be reflected in the returned list. Unlike Arrays.asList
, the returned list is unmodifiable. This is useful when a varargs method needs to use a signature such as (Foo firstFoo,
Foo... moreFoos)
, in order to avoid overload ambiguity or to enforce a minimum argument count.
The returned list is serializable and implements RandomAccess
.
Params: - first – the first element
- rest – an array of additional elements, possibly empty
Returns: an unmodifiable list containing the specified elements
/**
* Returns an unmodifiable list containing the specified first element and backed by the specified
* array of additional elements. Changes to the {@code rest} array will be reflected in the
* returned list. Unlike {@link Arrays#asList}, the returned list is unmodifiable.
*
* <p>This is useful when a varargs method needs to use a signature such as {@code (Foo firstFoo,
* Foo... moreFoos)}, in order to avoid overload ambiguity or to enforce a minimum argument count.
*
* <p>The returned list is serializable and implements {@link RandomAccess}.
*
* @param first the first element
* @param rest an array of additional elements, possibly empty
* @return an unmodifiable list containing the specified elements
*/
public static <E> List<E> asList(@Nullable E first, E[] rest) {
return new OnePlusArrayList<>(first, rest);
}
Returns an unmodifiable list containing the specified first and second element, and backed by the specified array of additional elements. Changes to the rest
array will be reflected in the returned list. Unlike Arrays.asList
, the returned list is unmodifiable. This is useful when a varargs method needs to use a signature such as (Foo firstFoo,
Foo secondFoo, Foo... moreFoos)
, in order to avoid overload ambiguity or to enforce a minimum argument count.
The returned list is serializable and implements RandomAccess
.
Params: - first – the first element
- second – the second element
- rest – an array of additional elements, possibly empty
Returns: an unmodifiable list containing the specified elements
/**
* Returns an unmodifiable list containing the specified first and second element, and backed by
* the specified array of additional elements. Changes to the {@code rest} array will be reflected
* in the returned list. Unlike {@link Arrays#asList}, the returned list is unmodifiable.
*
* <p>This is useful when a varargs method needs to use a signature such as {@code (Foo firstFoo,
* Foo secondFoo, Foo... moreFoos)}, in order to avoid overload ambiguity or to enforce a minimum
* argument count.
*
* <p>The returned list is serializable and implements {@link RandomAccess}.
*
* @param first the first element
* @param second the second element
* @param rest an array of additional elements, possibly empty
* @return an unmodifiable list containing the specified elements
*/
public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
return new TwoPlusArrayList<>(first, second, rest);
}
See Also:
/** @see Lists#asList(Object, Object[]) */
private static class OnePlusArrayList<E> extends AbstractList<E>
implements Serializable, RandomAccess {
final @Nullable E first;
final E[] rest;
OnePlusArrayList(@Nullable E first, E[] rest) {
this.first = first;
this.rest = checkNotNull(rest);
}
@Override
public int size() {
return IntMath.saturatedAdd(rest.length, 1);
}
@Override
public E get(int index) {
// check explicitly so the IOOBE will have the right message
checkElementIndex(index, size());
return (index == 0) ? first : rest[index - 1];
}
private static final long serialVersionUID = 0;
}
See Also:
/** @see Lists#asList(Object, Object, Object[]) */
private static class TwoPlusArrayList<E> extends AbstractList<E>
implements Serializable, RandomAccess {
final @Nullable E first;
final @Nullable E second;
final E[] rest;
TwoPlusArrayList(@Nullable E first, @Nullable E second, E[] rest) {
this.first = first;
this.second = second;
this.rest = checkNotNull(rest);
}
@Override
public int size() {
return IntMath.saturatedAdd(rest.length, 2);
}
@Override
public E get(int index) {
switch (index) {
case 0:
return first;
case 1:
return second;
default:
// check explicitly so the IOOBE will have the right message
checkElementIndex(index, size());
return rest[index - 2];
}
}
private static final long serialVersionUID = 0;
}
Returns every possible list that can be formed by choosing one element from each of the given
lists in order; the "n-ary Cartesian
product" of the lists. For example:
Lists.cartesianProduct(ImmutableList.of(
ImmutableList.of(1, 2),
ImmutableList.of("A", "B", "C")))
returns a list containing six lists in the following order:
ImmutableList.of(1, "A")
ImmutableList.of(1, "B")
ImmutableList.of(1, "C")
ImmutableList.of(2, "A")
ImmutableList.of(2, "B")
ImmutableList.of(2, "C")
The result is guaranteed to be in the "traditional", lexicographical order for Cartesian
products that you would get from nesting for loops:
for (B b0 : lists.get(0)) {
for (B b1 : lists.get(1)) {
...
ImmutableList<B> tuple = ImmutableList.of(b0, b1, ...);
// operate on tuple
}
}
Note that if any input list is empty, the Cartesian product will also be empty. If no lists
at all are provided (an empty list), the resulting Cartesian product has one element, an empty
list (counter-intuitive, but mathematically consistent).
Performance notes: while the cartesian product of lists of size m, n, p
is a list of size m x n x p
, its actual memory consumption is much smaller. When the cartesian product is constructed, the input lists are merely copied. Only as the resulting list is iterated are the individual lists created, and these are not retained after iteration.
Params: - lists – the lists to choose elements from, in the order that the elements chosen from
those lists should appear in the resulting lists
Type parameters: Throws: - IllegalArgumentException – if the size of the cartesian product would be greater than
Integer.MAX_VALUE
- NullPointerException – if
lists
, any one of the lists
, or any element of a provided list is null
Returns: the Cartesian product, as an immutable list containing immutable lists Since: 19.0
/**
* Returns every possible list that can be formed by choosing one element from each of the given
* lists in order; the "n-ary <a href="http://en.wikipedia.org/wiki/Cartesian_product">Cartesian
* product</a>" of the lists. For example:
*
* <pre>{@code
* Lists.cartesianProduct(ImmutableList.of(
* ImmutableList.of(1, 2),
* ImmutableList.of("A", "B", "C")))
* }</pre>
*
* <p>returns a list containing six lists in the following order:
*
* <ul>
* <li>{@code ImmutableList.of(1, "A")}
* <li>{@code ImmutableList.of(1, "B")}
* <li>{@code ImmutableList.of(1, "C")}
* <li>{@code ImmutableList.of(2, "A")}
* <li>{@code ImmutableList.of(2, "B")}
* <li>{@code ImmutableList.of(2, "C")}
* </ul>
*
* <p>The result is guaranteed to be in the "traditional", lexicographical order for Cartesian
* products that you would get from nesting for loops:
*
* <pre>{@code
* for (B b0 : lists.get(0)) {
* for (B b1 : lists.get(1)) {
* ...
* ImmutableList<B> tuple = ImmutableList.of(b0, b1, ...);
* // operate on tuple
* }
* }
* }</pre>
*
* <p>Note that if any input list is empty, the Cartesian product will also be empty. If no lists
* at all are provided (an empty list), the resulting Cartesian product has one element, an empty
* list (counter-intuitive, but mathematically consistent).
*
* <p><i>Performance notes:</i> while the cartesian product of lists of size {@code m, n, p} is a
* list of size {@code m x n x p}, its actual memory consumption is much smaller. When the
* cartesian product is constructed, the input lists are merely copied. Only as the resulting list
* is iterated are the individual lists created, and these are not retained after iteration.
*
* @param lists the lists to choose elements from, in the order that the elements chosen from
* those lists should appear in the resulting lists
* @param <B> any common base class shared by all axes (often just {@link Object})
* @return the Cartesian product, as an immutable list containing immutable lists
* @throws IllegalArgumentException if the size of the cartesian product would be greater than
* {@link Integer#MAX_VALUE}
* @throws NullPointerException if {@code lists}, any one of the {@code lists}, or any element of
* a provided list is null
* @since 19.0
*/
public static <B> List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists) {
return CartesianList.create(lists);
}
Returns every possible list that can be formed by choosing one element from each of the given
lists in order; the "n-ary Cartesian
product" of the lists. For example:
Lists.cartesianProduct(ImmutableList.of(
ImmutableList.of(1, 2),
ImmutableList.of("A", "B", "C")))
returns a list containing six lists in the following order:
ImmutableList.of(1, "A")
ImmutableList.of(1, "B")
ImmutableList.of(1, "C")
ImmutableList.of(2, "A")
ImmutableList.of(2, "B")
ImmutableList.of(2, "C")
The result is guaranteed to be in the "traditional", lexicographical order for Cartesian
products that you would get from nesting for loops:
for (B b0 : lists.get(0)) {
for (B b1 : lists.get(1)) {
...
ImmutableList<B> tuple = ImmutableList.of(b0, b1, ...);
// operate on tuple
}
}
Note that if any input list is empty, the Cartesian product will also be empty. If no lists
at all are provided (an empty list), the resulting Cartesian product has one element, an empty
list (counter-intuitive, but mathematically consistent).
Performance notes: while the cartesian product of lists of size m, n, p
is a list of size m x n x p
, its actual memory consumption is much smaller. When the cartesian product is constructed, the input lists are merely copied. Only as the resulting list is iterated are the individual lists created, and these are not retained after iteration.
Params: - lists – the lists to choose elements from, in the order that the elements chosen from
those lists should appear in the resulting lists
Type parameters: Throws: - IllegalArgumentException – if the size of the cartesian product would be greater than
Integer.MAX_VALUE
- NullPointerException – if
lists
, any one of the lists
, or any element of a provided list is null
Returns: the Cartesian product, as an immutable list containing immutable lists Since: 19.0
/**
* Returns every possible list that can be formed by choosing one element from each of the given
* lists in order; the "n-ary <a href="http://en.wikipedia.org/wiki/Cartesian_product">Cartesian
* product</a>" of the lists. For example:
*
* <pre>{@code
* Lists.cartesianProduct(ImmutableList.of(
* ImmutableList.of(1, 2),
* ImmutableList.of("A", "B", "C")))
* }</pre>
*
* <p>returns a list containing six lists in the following order:
*
* <ul>
* <li>{@code ImmutableList.of(1, "A")}
* <li>{@code ImmutableList.of(1, "B")}
* <li>{@code ImmutableList.of(1, "C")}
* <li>{@code ImmutableList.of(2, "A")}
* <li>{@code ImmutableList.of(2, "B")}
* <li>{@code ImmutableList.of(2, "C")}
* </ul>
*
* <p>The result is guaranteed to be in the "traditional", lexicographical order for Cartesian
* products that you would get from nesting for loops:
*
* <pre>{@code
* for (B b0 : lists.get(0)) {
* for (B b1 : lists.get(1)) {
* ...
* ImmutableList<B> tuple = ImmutableList.of(b0, b1, ...);
* // operate on tuple
* }
* }
* }</pre>
*
* <p>Note that if any input list is empty, the Cartesian product will also be empty. If no lists
* at all are provided (an empty list), the resulting Cartesian product has one element, an empty
* list (counter-intuitive, but mathematically consistent).
*
* <p><i>Performance notes:</i> while the cartesian product of lists of size {@code m, n, p} is a
* list of size {@code m x n x p}, its actual memory consumption is much smaller. When the
* cartesian product is constructed, the input lists are merely copied. Only as the resulting list
* is iterated are the individual lists created, and these are not retained after iteration.
*
* @param lists the lists to choose elements from, in the order that the elements chosen from
* those lists should appear in the resulting lists
* @param <B> any common base class shared by all axes (often just {@link Object})
* @return the Cartesian product, as an immutable list containing immutable lists
* @throws IllegalArgumentException if the size of the cartesian product would be greater than
* {@link Integer#MAX_VALUE}
* @throws NullPointerException if {@code lists}, any one of the {@code lists}, or any element of
* a provided list is null
* @since 19.0
*/
@SafeVarargs
public static <B> List<List<B>> cartesianProduct(List<? extends B>... lists) {
return cartesianProduct(Arrays.asList(lists));
}
Returns a list that applies function
to each element of fromList
. The returned list is a transformed view of fromList
; changes to fromList
will be reflected in the returned list and vice versa. Since functions are not reversible, the transform is one-way and new items cannot be stored in the returned list. The add
, addAll
and set
methods are unsupported in the returned list.
The function is applied lazily, invoked when needed. This is necessary for the returned list to be a view, but it means that the function will be applied many times for bulk operations like List.contains
and List.hashCode
. For this to perform well,
function
should be fast. To avoid lazy evaluation when the returned list doesn't need to be a view, copy the returned list into a new list of your choosing.
If fromList
implements RandomAccess
, so will the returned list. The returned list is threadsafe if the supplied list and function are.
If only a Collection
or Iterable
input is available, use Collections2.transform
or Iterables.transform
.
Note: serializing the returned list is implemented by serializing fromList
, its contents, and function
-- not by serializing the transformed values. This
can lead to surprising behavior, so serializing the returned list is not recommended. Instead, copy the list using ImmutableList.copyOf(Collection<? extends Object>)
(for example), then serialize the copy. Other methods similar to this do not implement serialization at all for this reason.
Java 8 users: many use cases for this method are better addressed by Stream.map
. This method is not being deprecated, but we gently encourage you to migrate to streams.
/**
* Returns a list that applies {@code function} to each element of {@code fromList}. The returned
* list is a transformed view of {@code fromList}; changes to {@code fromList} will be reflected
* in the returned list and vice versa.
*
* <p>Since functions are not reversible, the transform is one-way and new items cannot be stored
* in the returned list. The {@code add}, {@code addAll} and {@code set} methods are unsupported
* in the returned list.
*
* <p>The function is applied lazily, invoked when needed. This is necessary for the returned list
* to be a view, but it means that the function will be applied many times for bulk operations
* like {@link List#contains} and {@link List#hashCode}. For this to perform well, {@code
* function} should be fast. To avoid lazy evaluation when the returned list doesn't need to be a
* view, copy the returned list into a new list of your choosing.
*
* <p>If {@code fromList} implements {@link RandomAccess}, so will the returned list. The returned
* list is threadsafe if the supplied list and function are.
*
* <p>If only a {@code Collection} or {@code Iterable} input is available, use {@link
* Collections2#transform} or {@link Iterables#transform}.
*
* <p><b>Note:</b> serializing the returned list is implemented by serializing {@code fromList},
* its contents, and {@code function} -- <i>not</i> by serializing the transformed values. This
* can lead to surprising behavior, so serializing the returned list is <b>not recommended</b>.
* Instead, copy the list using {@link ImmutableList#copyOf(Collection)} (for example), then
* serialize the copy. Other methods similar to this do not implement serialization at all for
* this reason.
*
* <p><b>Java 8 users:</b> many use cases for this method are better addressed by {@link
* java.util.stream.Stream#map}. This method is not being deprecated, but we gently encourage you
* to migrate to streams.
*/
public static <F, T> List<T> transform(
List<F> fromList, Function<? super F, ? extends T> function) {
return (fromList instanceof RandomAccess)
? new TransformingRandomAccessList<>(fromList, function)
: new TransformingSequentialList<>(fromList, function);
}
Implementation of a sequential transforming list.
See Also: - transform.transform
/**
* Implementation of a sequential transforming list.
*
* @see Lists#transform
*/
private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
implements Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);
this.function = checkNotNull(function);
}
The default implementation inherited is based on iteration and removal of each element which
can be overkill. That's why we forward this call directly to the backing list.
/**
* The default implementation inherited is based on iteration and removal of each element which
* can be overkill. That's why we forward this call directly to the backing list.
*/
@Override
public void clear() {
fromList.clear();
}
@Override
public int size() {
return fromList.size();
}
@Override
public ListIterator<T> listIterator(final int index) {
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
return function.apply(from);
}
};
}
@Override
public boolean removeIf(Predicate<? super T> filter) {
checkNotNull(filter);
return fromList.removeIf(element -> filter.test(function.apply(element)));
}
private static final long serialVersionUID = 0;
}
Implementation of a transforming random access list. We try to make as many of these methods
pass-through to the source list as possible so that the performance characteristics of the
source list and transformed list are similar.
See Also: - transform.transform
/**
* Implementation of a transforming random access list. We try to make as many of these methods
* pass-through to the source list as possible so that the performance characteristics of the
* source list and transformed list are similar.
*
* @see Lists#transform
*/
private static class TransformingRandomAccessList<F, T> extends AbstractList<T>
implements RandomAccess, Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);
this.function = checkNotNull(function);
}
@Override
public void clear() {
fromList.clear();
}
@Override
public T get(int index) {
return function.apply(fromList.get(index));
}
@Override
public Iterator<T> iterator() {
return listIterator();
}
@Override
public ListIterator<T> listIterator(int index) {
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
return function.apply(from);
}
};
}
@Override
public boolean isEmpty() {
return fromList.isEmpty();
}
@Override
public boolean removeIf(Predicate<? super T> filter) {
checkNotNull(filter);
return fromList.removeIf(element -> filter.test(function.apply(element)));
}
@Override
public T remove(int index) {
return function.apply(fromList.remove(index));
}
@Override
public int size() {
return fromList.size();
}
private static final long serialVersionUID = 0;
}
Returns consecutive sublists of a list, each of the same size (the final list may be smaller). For example, partitioning a list containing [a, b,
c, d, e]
with a partition size of 3 yields [[a, b, c], [d, e]]
-- an outer list containing two inner lists of three and two elements, all in the original order. The outer list is unmodifiable, but reflects the latest state of the source list. The inner lists are sublist views of the original list, produced on demand using List.subList(int, int)
, and are subject to all the usual caveats about modification as explained in that API.
Params: - list – the list to return consecutive sublists of
- size – the desired size of each sublist (the last may be smaller)
Throws: - IllegalArgumentException – if
partitionSize
is nonpositive
Returns: a list of consecutive sublists
/**
* Returns consecutive {@linkplain List#subList(int, int) sublists} of a list, each of the same
* size (the final list may be smaller). For example, partitioning a list containing {@code [a, b,
* c, d, e]} with a partition size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list
* containing two inner lists of three and two elements, all in the original order.
*
* <p>The outer list is unmodifiable, but reflects the latest state of the source list. The inner
* lists are sublist views of the original list, produced on demand using {@link List#subList(int,
* int)}, and are subject to all the usual caveats about modification as explained in that API.
*
* @param list the list to return consecutive sublists of
* @param size the desired size of each sublist (the last may be smaller)
* @return a list of consecutive sublists
* @throws IllegalArgumentException if {@code partitionSize} is nonpositive
*/
public static <T> List<List<T>> partition(List<T> list, int size) {
checkNotNull(list);
checkArgument(size > 0);
return (list instanceof RandomAccess)
? new RandomAccessPartition<>(list, size)
: new Partition<>(list, size);
}
private static class Partition<T> extends AbstractList<List<T>> {
final List<T> list;
final int size;
Partition(List<T> list, int size) {
this.list = list;
this.size = size;
}
@Override
public List<T> get(int index) {
checkElementIndex(index, size());
int start = index * size;
int end = Math.min(start + size, list.size());
return list.subList(start, end);
}
@Override
public int size() {
return IntMath.divide(list.size(), size, RoundingMode.CEILING);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
}
private static class RandomAccessPartition<T> extends Partition<T> implements RandomAccess {
RandomAccessPartition(List<T> list, int size) {
super(list, size);
}
}
Returns a view of the specified string as an immutable list of Character
values. Since: 7.0
/**
* Returns a view of the specified string as an immutable list of {@code Character} values.
*
* @since 7.0
*/
public static ImmutableList<Character> charactersOf(String string) {
return new StringAsImmutableList(checkNotNull(string));
}
Returns a view of the specified CharSequence
as a List<Character>
, viewing sequence
as a sequence of Unicode code units. The view does not support any modification operations, but reflects any changes to the underlying character sequence. Params: - sequence – the character sequence to view as a
List
of characters
Returns: an List<Character>
view of the character sequence Since: 7.0
/**
* Returns a view of the specified {@code CharSequence} as a {@code List<Character>}, viewing
* {@code sequence} as a sequence of Unicode code units. The view does not support any
* modification operations, but reflects any changes to the underlying character sequence.
*
* @param sequence the character sequence to view as a {@code List} of characters
* @return an {@code List<Character>} view of the character sequence
* @since 7.0
*/
@Beta
public static List<Character> charactersOf(CharSequence sequence) {
return new CharSequenceAsList(checkNotNull(sequence));
}
@SuppressWarnings("serial") // serialized using ImmutableList serialization
private static final class StringAsImmutableList extends ImmutableList<Character> {
private final String string;
StringAsImmutableList(String string) {
this.string = string;
}
@Override
public int indexOf(@Nullable Object object) {
return (object instanceof Character) ? string.indexOf((Character) object) : -1;
}
@Override
public int lastIndexOf(@Nullable Object object) {
return (object instanceof Character) ? string.lastIndexOf((Character) object) : -1;
}
@Override
public ImmutableList<Character> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size()); // for GWT
return charactersOf(string.substring(fromIndex, toIndex));
}
@Override
boolean isPartialView() {
return false;
}
@Override
public Character get(int index) {
checkElementIndex(index, size()); // for GWT
return string.charAt(index);
}
@Override
public int size() {
return string.length();
}
}
private static final class CharSequenceAsList extends AbstractList<Character> {
private final CharSequence sequence;
CharSequenceAsList(CharSequence sequence) {
this.sequence = sequence;
}
@Override
public Character get(int index) {
checkElementIndex(index, size()); // for GWT
return sequence.charAt(index);
}
@Override
public int size() {
return sequence.length();
}
}
Returns a reversed view of the specified list. For example,
Lists.reverse(Arrays.asList(1, 2, 3))
returns a list containing 3, 2, 1
. The returned list is backed by this list, so changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list. The returned list is random-access if the specified list is random access.
Since: 7.0
/**
* Returns a reversed view of the specified list. For example, {@code
* Lists.reverse(Arrays.asList(1, 2, 3))} returns a list containing {@code 3, 2, 1}. The returned
* list is backed by this list, so changes in the returned list are reflected in this list, and
* vice-versa. The returned list supports all of the optional list operations supported by this
* list.
*
* <p>The returned list is random-access if the specified list is random access.
*
* @since 7.0
*/
public static <T> List<T> reverse(List<T> list) {
if (list instanceof ImmutableList) {
return ((ImmutableList<T>) list).reverse();
} else if (list instanceof ReverseList) {
return ((ReverseList<T>) list).getForwardList();
} else if (list instanceof RandomAccess) {
return new RandomAccessReverseList<>(list);
} else {
return new ReverseList<>(list);
}
}
private static class ReverseList<T> extends AbstractList<T> {
private final List<T> forwardList;
ReverseList(List<T> forwardList) {
this.forwardList = checkNotNull(forwardList);
}
List<T> getForwardList() {
return forwardList;
}
private int reverseIndex(int index) {
int size = size();
checkElementIndex(index, size);
return (size - 1) - index;
}
private int reversePosition(int index) {
int size = size();
checkPositionIndex(index, size);
return size - index;
}
@Override
public void add(int index, @Nullable T element) {
forwardList.add(reversePosition(index), element);
}
@Override
public void clear() {
forwardList.clear();
}
@Override
public T remove(int index) {
return forwardList.remove(reverseIndex(index));
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
subList(fromIndex, toIndex).clear();
}
@Override
public T set(int index, @Nullable T element) {
return forwardList.set(reverseIndex(index), element);
}
@Override
public T get(int index) {
return forwardList.get(reverseIndex(index));
}
@Override
public int size() {
return forwardList.size();
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
return reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)));
}
@Override
public Iterator<T> iterator() {
return listIterator();
}
@Override
public ListIterator<T> listIterator(int index) {
int start = reversePosition(index);
final ListIterator<T> forwardIterator = forwardList.listIterator(start);
return new ListIterator<T>() {
boolean canRemoveOrSet;
@Override
public void add(T e) {
forwardIterator.add(e);
forwardIterator.previous();
canRemoveOrSet = false;
}
@Override
public boolean hasNext() {
return forwardIterator.hasPrevious();
}
@Override
public boolean hasPrevious() {
return forwardIterator.hasNext();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
canRemoveOrSet = true;
return forwardIterator.previous();
}
@Override
public int nextIndex() {
return reversePosition(forwardIterator.nextIndex());
}
@Override
public T previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
canRemoveOrSet = true;
return forwardIterator.next();
}
@Override
public int previousIndex() {
return nextIndex() - 1;
}
@Override
public void remove() {
checkRemove(canRemoveOrSet);
forwardIterator.remove();
canRemoveOrSet = false;
}
@Override
public void set(T e) {
checkState(canRemoveOrSet);
forwardIterator.set(e);
}
};
}
}
private static class RandomAccessReverseList<T> extends ReverseList<T> implements RandomAccess {
RandomAccessReverseList(List<T> forwardList) {
super(forwardList);
}
}
An implementation of List.hashCode()
. /** An implementation of {@link List#hashCode()}. */
static int hashCodeImpl(List<?> list) {
// TODO(lowasser): worth optimizing for RandomAccess?
int hashCode = 1;
for (Object o : list) {
hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
hashCode = ~~hashCode;
// needed to deal with GWT integer overflow
}
return hashCode;
}
An implementation of List.equals(Object)
. /** An implementation of {@link List#equals(Object)}. */
static boolean equalsImpl(List<?> thisList, @Nullable Object other) {
if (other == checkNotNull(thisList)) {
return true;
}
if (!(other instanceof List)) {
return false;
}
List<?> otherList = (List<?>) other;
int size = thisList.size();
if (size != otherList.size()) {
return false;
}
if (thisList instanceof RandomAccess && otherList instanceof RandomAccess) {
// avoid allocation and use the faster loop
for (int i = 0; i < size; i++) {
if (!Objects.equal(thisList.get(i), otherList.get(i))) {
return false;
}
}
return true;
} else {
return Iterators.elementsEqual(thisList.iterator(), otherList.iterator());
}
}
An implementation of List.addAll(int, Collection)
. /** An implementation of {@link List#addAll(int, Collection)}. */
static <E> boolean addAllImpl(List<E> list, int index, Iterable<? extends E> elements) {
boolean changed = false;
ListIterator<E> listIterator = list.listIterator(index);
for (E e : elements) {
listIterator.add(e);
changed = true;
}
return changed;
}
An implementation of List.indexOf(Object)
. /** An implementation of {@link List#indexOf(Object)}. */
static int indexOfImpl(List<?> list, @Nullable Object element) {
if (list instanceof RandomAccess) {
return indexOfRandomAccess(list, element);
} else {
ListIterator<?> listIterator = list.listIterator();
while (listIterator.hasNext()) {
if (Objects.equal(element, listIterator.next())) {
return listIterator.previousIndex();
}
}
return -1;
}
}
private static int indexOfRandomAccess(List<?> list, @Nullable Object element) {
int size = list.size();
if (element == null) {
for (int i = 0; i < size; i++) {
if (list.get(i) == null) {
return i;
}
}
} else {
for (int i = 0; i < size; i++) {
if (element.equals(list.get(i))) {
return i;
}
}
}
return -1;
}
An implementation of List.lastIndexOf(Object)
. /** An implementation of {@link List#lastIndexOf(Object)}. */
static int lastIndexOfImpl(List<?> list, @Nullable Object element) {
if (list instanceof RandomAccess) {
return lastIndexOfRandomAccess(list, element);
} else {
ListIterator<?> listIterator = list.listIterator(list.size());
while (listIterator.hasPrevious()) {
if (Objects.equal(element, listIterator.previous())) {
return listIterator.nextIndex();
}
}
return -1;
}
}
private static int lastIndexOfRandomAccess(List<?> list, @Nullable Object element) {
if (element == null) {
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) == null) {
return i;
}
}
} else {
for (int i = list.size() - 1; i >= 0; i--) {
if (element.equals(list.get(i))) {
return i;
}
}
}
return -1;
}
Returns an implementation of List.listIterator(int)
. /** Returns an implementation of {@link List#listIterator(int)}. */
static <E> ListIterator<E> listIteratorImpl(List<E> list, int index) {
return new AbstractListWrapper<>(list).listIterator(index);
}
An implementation of List.subList(int, int)
. /** An implementation of {@link List#subList(int, int)}. */
static <E> List<E> subListImpl(final List<E> list, int fromIndex, int toIndex) {
List<E> wrapper;
if (list instanceof RandomAccess) {
wrapper =
new RandomAccessListWrapper<E>(list) {
@Override
public ListIterator<E> listIterator(int index) {
return backingList.listIterator(index);
}
private static final long serialVersionUID = 0;
};
} else {
wrapper =
new AbstractListWrapper<E>(list) {
@Override
public ListIterator<E> listIterator(int index) {
return backingList.listIterator(index);
}
private static final long serialVersionUID = 0;
};
}
return wrapper.subList(fromIndex, toIndex);
}
private static class AbstractListWrapper<E> extends AbstractList<E> {
final List<E> backingList;
AbstractListWrapper(List<E> backingList) {
this.backingList = checkNotNull(backingList);
}
@Override
public void add(int index, E element) {
backingList.add(index, element);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return backingList.addAll(index, c);
}
@Override
public E get(int index) {
return backingList.get(index);
}
@Override
public E remove(int index) {
return backingList.remove(index);
}
@Override
public E set(int index, E element) {
return backingList.set(index, element);
}
@Override
public boolean contains(Object o) {
return backingList.contains(o);
}
@Override
public int size() {
return backingList.size();
}
}
private static class RandomAccessListWrapper<E> extends AbstractListWrapper<E>
implements RandomAccess {
RandomAccessListWrapper(List<E> backingList) {
super(backingList);
}
}
Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 /** Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 */
static <T> List<T> cast(Iterable<T> iterable) {
return (List<T>) iterable;
}
}