No dudes en compartir nuestro sitio y códigos en tus redes sociales, apóyanos para ampliar nuestra comunidad.
Solución:
Puedes resolver esto usando el recursivo flatMap
cadena.
Primero, como necesitamos movernos hacia adelante y hacia atrás por los valores del mapa, es mejor copiarlos en el ArrayList
(esta no es la copia profunda, en tu caso es ArrayList
de solo 3 elementos, por lo que el uso de memoria adicional es bajo).
En segundo lugar, para mantener un prefix de los elementos visitados anteriormente, creemos un ayudante inmutable Prefix
clase:
private static class Prefix
final T value;
final Prefix parent;
Prefix(Prefix parent, T value)
this.parent = parent;
this.value = value;
// put the whole prefix into given collection
> C addTo(C collection)
if (parent != null)
parent.addTo(collection);
collection.add(value);
return collection;
Esta es una lista enlazada inmutable muy simple que se puede usar así:
List list = new Prefix<>(new Prefix<>(new Prefix<>(null, "a"), "b"), "c")
.addTo(new ArrayList<>()); // [a, b, c];
A continuación, creemos el método interno que encadena flatMaps:
private static > Stream comb(
List extends Collection> values, int offset, Prefix prefix,
Supplier supplier)
if (offset == values.size() - 1)
return values.get(offset).stream()
.map(e -> new Prefix<>(prefix, e).addTo(supplier.get()));
return values.get(offset).stream()
.flatMap(e -> comb(values, offset + 1, new Prefix<>(prefix, e), supplier));
Parece recursividad, pero es más complejo: no se llama a sí mismo directamente, sino que pasa lambda que llama al método externo. Parámetros:
- valores: el
List
de valores originales (new ArrayList<>(map.values)
en tu caso). - desplazamiento: el desplazamiento actual dentro de esta lista
- prefix: la corriente prefix de desplazamiento de longitud (o
null
Sioffset == 0
). Contiene elementos seleccionados actualmente de las colecciones.list.get(0)
,list.get(1)
hastalist.get(offset-1)
. - proveedor: el método de fábrica para crear la colección resultante.
Cuando llegamos al final de la lista de valores (offset == values.size() - 1
), mapeamos los elementos de la última colección desde los valores hasta la combinación final utilizando el proveedor. De lo contrario usamos el flatMap
que para cada elemento intermedio agranda el prefix y llama al comb
método de nuevo para el próximo desplazamiento.
Finalmente, aquí está el método público para usar esta función:
public static > Stream ofCombinations(
Collection extends Collection> values, Supplier supplier)
if (values.isEmpty())
return Stream.empty();
return comb(new ArrayList<>(values), 0, null, supplier);
Un ejemplo de uso:
Map> map = new LinkedHashMap<>(); // to preserve the order
map.put("A", Arrays.asList("a1", "a2", "a3", "a4"));
map.put("B", Arrays.asList("b1", "b2", "b3"));
map.put("C", Arrays.asList("c1", "c2"));
ofCombinations(map.values(), LinkedHashSet::new).forEach(System.out::println);
Recopilamos combinaciones individuales para LinkedHashSet
de nuevo para preservar el orden. En su lugar, puede utilizar cualquier otra colección (p. Ej. ArrayList::new
).
Una solución que opera principalmente sobre listas, simplificando mucho las cosas. Hace una llamada recursiva flatMap
, realiza un seguimiento de los elementos que ya se han combinado y las colecciones de elementos que aún faltan, y ofrece los resultados de esta construcción recursiva anidada como un flujo de listas:
import java.util.*;
import java.util.stream.Stream;
public class CartesianProduct
public static void main(String[] args)
Map> map =
new LinkedHashMap>();
map.put("A", Arrays.asList("a1", "a2", "a3", "a4"));
map.put("B", Arrays.asList("b1", "b2", "b3"));
map.put("C", Arrays.asList("c1", "c2"));
ofCombinations(map.values()).forEach(System.out::println);
public static Stream> ofCombinations(
Collection extends Collection> collections)
return ofCombinations(
new ArrayList>(collections),
Collections.emptyList());
private static Stream> ofCombinations(
List extends Collection> collections, List current)
return collections.isEmpty() ? Stream.of(current) :
collections.get(0).stream().flatMap(e ->
List list = new ArrayList(current);
list.add(e);
return ofCombinations(
collections.subList(1, collections.size()), list);
);
Producto cartesiano en Java 8 con forEach:
List listA = new ArrayList<>();
listA.add("0");
listA.add("1");
List listB = new ArrayList<>();
listB.add("a");
listB.add("b");
List cartesianProduct = new ArrayList<>();
listA.forEach(a -> listB.forEach(b -> cartesianProduct.add(a + b)));
cartesianProduct.forEach(System.out::println);
//Output : 0a 0b 1a 1b
valoraciones y reseñas
Si haces scroll puedes encontrar las reseñas de otros usuarios, tú asimismo tienes la habilidad dejar el tuyo si te apetece.