Как создать декартово произведение в Java?

90
10

У меня есть число ArrayList с каждым ArrayList, имеющим объекты, и каждый из них может иметь разную длину. Мне нужно создать перестановку, как в приведенном ниже примере:


предположим, что у меня есть 2 arraylist


arraylist A имеет объект a, объект b и объект c
arraylist B имеет объект d, объект e



Тогда выход должен состоять из 6 новых arraylist с этими комбинациями:


комбинация 1 объект a и объект d,
комбинация 2 объекта a и объекта e,
комбинация 3 объекта b и объекта d,
комбинация 4 объекта b и объекта e,
комбинация 5 объектов c и объекта d,
комбинация 6 объекта c и объекта e,



Кто-нибудь может мне помочь?

спросил(а) 2011-11-10T19:13:00+04:00 8 лет назад
4
Решение
85

Гуава 19 +


Lists.cartesianProduct(List...)

.

например

List<Object> list1 = Arrays.asList("a", "b", "c");
List<Object> list2 = Arrays.asList("d", "e");
System.out.println(Lists.cartesianProduct(list1, list2));

Выход


[[a, d], [a, e], [b, d], [b, e], [c, d], [c, e]]

ответил(а) 2016-12-04T12:56:00+03:00 3 года назад
Еще 3 ответа
78

С Java8 потоками


    List<String> a = Arrays.asList("a", "b", "c");
List<String> b = Arrays.asList("d", "e");
String[][] AB = a.stream().flatMap(ai -> b.stream().map(bi -> new String[] { ai, bi })).toArray(String[][]::new);
System.out.println(Arrays.deepToString(AB));

Выход

    [[a, d], [a, e], [b, d], [b, e], [c, d], [c, e]]

Чтобы получить как List


    List<List<String>> ll = a.stream().flatMap(ai -> b.stream().map(bi -> new ArrayList<>(Arrays.asList(ai, bi)))).collect(Collectors.toList());

ответил(а) 2016-10-23T15:08:00+03:00 3 года, 1 месяц назад
71

С Iterable + Iterator:


import java.util.*;

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> (); // no break past return;
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;
}
}
}
}

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);
}
}


Вы можете использовать их в упрощенном for-loop:


class CartesianIteratorTest {

public static void main (String[] args) {
List <Character> la = Arrays.asList (new Character [] {'a', 'b', 'c'});
List <Character> lb = Arrays.asList (new Character [] {'d', 'e'});
List <List <Character>> llc = new ArrayList <List <Character>> ();
llc.add (la);
llc.add (lb);

CartesianIterable <Character> ci = new CartesianIterable <Character> (llc);
for (List<Character> lo: ci)
show (lo);
}

public static void show (List <Character> lo) {
System.out.print ("(");
for (Object o: lo)
System.out.print (o);
System.out.println (")");
}
}

ответил(а) 2012-04-10T09:23:00+04:00 7 лет, 8 месяцев назад
32

Используйте вложенные для циклов, которые будут иметь цикл для каждого массива ArrayList, как показано ниже. Я предполагаю, что у меня есть два ArrayLists - intList и stringList. Для генерации перестановки у меня может быть два вложенных цикла (по одному для каждого списка).


    for(Integer i : intList){
for (String s : stringList) {
...
}
}

ответил(а) 2011-11-10T19:28:00+04:00 8 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема