java - otro - Cómo usar secuencias para encontrar pares de elementos de dos listas o multiplicación de matrices
multiplicacion de matrices con hilos java (5)
Tengo dos listas de números y me gustaría encontrar todos los pares de números posibles. Por ejemplo, dadas las listas [1, 2, 3] y [3, 4] el resultado debe ser [(1, 3), (1, 4), (2, 3), (2, 4), (3 , 3), (3, 4)].
Sé que puedo hacer esto usando un bucle for
pero ¿hay alguna forma más concisa de hacerlo usando flujos de Java 8?
Intenté lo siguiente, pero me estoy perdiendo algo porque obtengo la List<Stream<int[]>>
lugar de la List<int[]>
.
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(3, 4);
List<int[]> pairs = list1.stream().map(i -> list2.stream().map(j -> new int[] { i, j }))
.collect(Collectors.toList());
pairs.forEach(i -> {
System.out.println("{" + i[0]+ "," + i[1]+ "}");
});
}
Aquí hay una solución que usa IntStream
con dos arreglos int
como fuente en lugar de List<Integer>
. Quería ver si era posible resolver este problema sin encasillar todos los int
como un Integer
.
int[] one = new int[]{1, 2, 3};
int[] two = new int[]{3, 4};
List<IntIntPair> list = new ArrayList<>();
IntStream.of(one).forEach(i ->
IntStream.of(two).mapToObj(j -> PrimitiveTuples.pair(i, j)).forEach(list::add));
System.out.println(list);
// [1:3, 1:4, 2:3, 2:4, 3:3, 3:4]
Desafortunadamente, no pude usar flatMap
en IntStream
ya que devuelve un IntStream
. Actualmente no hay flatMapToObj
en IntStream
, que es lo que se necesitaría aquí. Así que usé forEach
en forEach
lugar.
Las clases IntIntPair
y PrimitiveTuples
que usé de Eclipse Collections , ya que simplificaron la salida de la lista como una cadena. Podría usar int[]
como lo tiene en su solución. El código se vería como sigue.
List<int[]> list = new ArrayList<>();
IntStream.of(one).forEach(i ->
IntStream.of(two).mapToObj(j -> new int[]{i, j}).forEach(list::add));
En la versión 8.1 de Eclipse Collections (que se lanzará a mediados de marzo), ahora existe un método flatCollect
en todos los contenedores primitivos de la biblioteca que se puede usar para resolver este problema. Básicamente, esto hace lo que debería hacer un método IntStream
en IntStream
.
IntList a = IntLists.mutable.with(1, 2, 3);
IntList b = IntLists.mutable.with(3, 4);
List<IntIntPair> result =
a.flatCollect(
i -> b.collect(j -> PrimitiveTuples.pair(i, j)),
Lists.mutable.empty());
System.out.println(result);
// [1:3, 1:4, 2:3, 2:4, 3:3, 3:4]
Actualizar:
Como se señaló en los comentarios de Boris the Spider, la solución forEach
no sería segura para subprocesos y se rompería si el IntStream
fuera parallel
. La siguiente solución debería funcionar en serie o en paralelo. Me alegro de que esto haya sido señalado, porque no había pensado hacer un mapToObj
en el IntStream
y luego seguí un flatMap
.
int[] one = new int[]{1, 2, 3};
int[] two = new int[]{3, 4};
List<int[]> list = IntStream.of(one).parallel()
.mapToObj(i -> IntStream.of(two).mapToObj(j -> new int[]{i, j}))
.flatMap(e -> e)
.collect(Collectors.toList());
list.stream().map(e -> "{" + e[0] + "," + e[1] + "}").forEach(System.out::println);
Nota: Soy un comendador de Eclipse Collections .
En este caso particular, utilizando flatMap
, incluso puede omitir una creación de matriz y hacer su código más simple así:
list1.stream()
.flatMap(i -> list2.stream().map(j -> "{" + i+ "," + j + "}"))
.forEach(System.out::println);
Solo necesitas reemplazar tu primer map()
con flatMap()
.
Use el método flatMap () en lugar de map () , combinará los flujos en uno. Consulte: Diferencia entre map () y flatMap () y flatMap () ejemplo
//return pair of numbers
List<List<Integer>> pairs=numbers.stream()
.flatMap(i -> numbers2.stream()
.map(j -> Arrays.asList(i,j)))
.collect(Collectors.toList());
pairs.stream().forEach(System.out::println);