Skip to content

Commit

Permalink
Implement Sets.cartesianProduct to iterate in lexicographical order. …
Browse files Browse the repository at this point in the history
…In the process, Lists.cartesianProduct has been implemented on a package-private basis.

-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=34279184
  • Loading branch information
cpovirk committed Sep 26, 2012
1 parent 79f5075 commit 86aa9f0
Show file tree
Hide file tree
Showing 8 changed files with 664 additions and 213 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ protected E get(int index) {
return this;
}

@Override
public boolean equals(@Nullable Object obj) {
return Lists.equalsImpl(this, obj);
}

@Override
public int hashCode() {
return Lists.hashCodeImpl(this);
}

public ImmutableList<E> reverse() {
List<E> list = Lists.newArrayList(this);
Collections.reverse(list);
Expand All @@ -275,9 +285,15 @@ public static <E> Builder<E> builder() {
}

public static final class Builder<E> extends ImmutableCollection.Builder<E> {
private final ArrayList<E> contents = Lists.newArrayList();
private final ArrayList<E> contents;

public Builder() {
contents = Lists.newArrayList();
}

public Builder() {}
Builder(int capacity) {
contents = Lists.newArrayListWithCapacity(capacity);
}

@Override public Builder<E> add(E element) {
contents.add(checkNotNull(element));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
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;
Expand Down Expand Up @@ -316,6 +317,127 @@ private static class TwoPlusArrayList<E> extends AbstractList<E>
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
* <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>
*
* 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>
*
* The result is guaranteed to be 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>
*
* 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
*/
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
* <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>
*
* 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>
*
* The result is guaranteed to be 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>
*
* 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
*/
static <B> List<List<B>> cartesianProduct(List<? extends B>... lists) {
return cartesianProduct(Arrays.asList(lists));
}

/**
* Returns a list that applies {@code function} to each element of {@code
* fromList}. The returned list is a transformed view of {@code fromList};
Expand Down Expand Up @@ -888,10 +1010,13 @@ private static class RandomAccessReverseList<T> extends ReverseList<T>
/**
* An implementation of {@link List#hashCode()}.
*/
static int hashCodeImpl(List<?> list){
static int hashCodeImpl(List<?> list) {
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;
}
Expand Down
Loading

0 comments on commit 86aa9f0

Please sign in to comment.