这里有一个可迭代对象,它允许您使用简化的for循环:
import java.util.*;
class CartesianIteratorTest {
public static void main (String[] args) {
List <Object> lc = Arrays.asList (new Object [] {'A', 'B', 'C', 'D'});
List <Object> lC = Arrays.asList (new Object [] {'a', 'b', 'c'});
List <Object> li = Arrays.asList (new Object [] {1, 2, 3, 4});
List <List <Object>> llo = new ArrayList <List <Object>> ();
llo.add (lc);
llo.add (lC);
llo.add (li);
CartesianIterable <Object> ci = new CartesianIterable <Object> (llo);
for (List <Object> lo: ci)
show (lo);
}
public static void show (List <Object> lo) {
System.out.print ("(");
for (Object o: lo)
System.out.print (o + ", ");
System.out.println (")");
}
}
这个功能是如何实现的?我们需要一个Iterable对象,以便使用简化版for循环,并且从Iterable中返回Iterator。我们返回一个对象列表 - 这可以是Set而不是List,但Set没有索引访问,所以使用Set代替List会更加复杂。与通用解决方案不同的是,对于许多目的来说,Object就足够了,但泛型允许更多的限制。
class CartesianIterator <T> implements Iterator <List <T>> {
private final List <List <T>> lilio;
private int current = 0;
private final long last;
public CartesianIterator (final List <List <T>> llo) {
lilio = llo;
long product = 1L;
for (List <T> lio: lilio)
product *= lio.size ();
last = product;
}
public boolean hasNext () {
return current != last;
}
public List <T> next () {
++current;
return get (current - 1, lilio);
}
public void remove () {
++current;
}
private List<T> get (final int n, final List <List <T>> lili) {
switch (lili.size ())
{
case 0: return new ArrayList <T> ();
default: {
List <T> inner = lili.get (0);
List <T> lo = new ArrayList <T> ();
lo.add (inner.get (n % inner.size ()));
lo.addAll (get (n / inner.size (), lili.subList (1, lili.size ())));
return lo;
}
}
}
}
数学工作是在“get”方法中完成的。想象一下有2组10个元素,你总共有100种组合,从00,01,02...10等枚举到99。对于5 X 10元素50,对于2 X 3元素6种组合。子列表大小的模可以帮助每次迭代选择一个元素。
在这里,可迭代对象是最不重要的事情:
class CartesianIterable <T> implements Iterable <List <T>> {
private List <List <T>> lilio;
public CartesianIterable (List <List <T>> llo) {
lilio = llo;
}
public Iterator <List <T>> iterator () {
return new CartesianIterator <T> (lilio);
}
}
要实现 Iterable 接口,以便使用 for-each 循环,我们需要实现 iterator() 方法。而对于 Iterator 接口,我们需要实现 hasNext()、next() 和 remove() 方法。
(A, a, 1, )
(B, a, 1, )
(C, a, 1, )
(D, a, 1, )
(A, b, 1, )
(B, b, 1, )
(C, b, 1, )
(D, b, 1, )
...
(A, a, 2, )
...
(C, c, 4, )
(D, c, 4, )
Set<List<Object>>
,否则你可能会在结果中得到不同大小的集合(因为有重复项)。 - MarcocartesianProduct
的参数更改为ArrayList,则返回的笛卡尔积将按相反的顺序返回。我的意思是,笛卡尔积的第一个元素将是给定的最后一个集合的元素。这是为什么? - foobarArrayList<ArrayList<Double>>
并以ArrayList<ArrayList<Double>>
数据类型返回方法?当我进行修改时,笛卡尔积的顺序会发生变化。 - foobar