Exigence:
Entrée: liste d'entiers.
Liste1: [1,2,3]
Liste 2: [4,5,6]
Liste 3: [7,8,9]
Sortie: [1, 4, 7, 2, 5, 8, 3, 6, 9]
Hypothèse: chaque liste sera de la même taille.
Voici ma mise en œuvre initiale qui, selon moi, n'est pas très optimale. Y a-t-il un meilleur moyen?
List<Integer> one = Arrays.asList(1, 2,3);
List<Integer> two = Arrays.asList(4, 5,6);
List<Integer> three = Arrays.asList(7, 8, 9);
List<Integer> out = new ArrayList<>();
for(int i=0; i< one.size(); i++){
final int index = i;
out.addAll(Stream.of(one, two, three)
.collect(ArrayList::new,
(listStream, item) -> listStream.add(item.get(index)),
(item1, item2) -> {}));
}
System.out.println(out);
Sortie: [1, 4, 7, 2, 5, 8, 3, 6, 9]
4 Réponses :
Vous pourriez faire
List<Integer> one = Arrays.asList(1, 2, 3);
List<Integer> two = Arrays.asList(4, 5, 6);
List<Integer> three = Arrays.asList(7, 8, 9);
List<Iterator<Integer>> its = Stream.of(one, two, three).map(Iterable::iterator).collect(Collectors.toList());
List<Integer> out = new ArrayList<>();
while (true) {
try {
for (Iterator<Integer> it : its) {
out.add(it.next());
}
} catch (NoSuchElementException ignored) {
break;
}
}
System.out.println(out);
Sortie: [1, 4, 7, 2, 5, 8, 3, 6, 9]
Si ces listes peuvent devenir longues, utiliser un itérateur pourrait être mieux que d'accéder aux éléments en utilisant get positionnel, par exemple
List<Integer> one = Arrays.asList(1, 2, 3);
List<Integer> two = Arrays.asList(4, 5, 6);
List<Integer> three = Arrays.asList(7, 8, 9);
List<List<Integer>> lists = Arrays.asList(one, two, three);
List<Integer> out = IntStream.range(0, one.size())
.mapToObj(i -> lists.stream().map(list -> list.get(i)))
.flatMap(Function.identity())
.collect(Collectors.toList());
System.out.println(out);
Tant qu'il s'agit d'itérer plusieurs collections simultanément, je préfère utiliser Iterator sur Stream API car vous avez plus de contrôle.
Iterator<Integer> iterator1 = one.iterator();
Iterator<Integer> iterator2 = two.iterator();
Iterator<Integer> iterator3 = three.iterator();
while (iterator1.hasNext() || iterator2.hasNext() || iterator3.hasNext()) {
if (iterator1.hasNext()) out.add(iterator1.next());
if (iterator2.hasNext()) out.add(iterator2.next());
if (iterator3.hasNext()) out.add(iterator3.next());
}
System.out.println(out);
Avantages:
Les inconvénients:
Iterator::hasNext .Vous pourriez le faire comme ça.
List<Integer> result2 = new ArrayList<>();
for (int i = 0; i < lists.get(0).size(); i++) {
for (List<Integer> lst : lists) {
result2.add(lst.get(i));
}
}
System.out.println(result2);
Tirages
[1, 4, 7, 2, 5, 8, 3, 6, 9]
Mais alors, cela fonctionne aussi.
List<List<Integer>> lists = List.of(List.of(1, 2, 3),
List.of(4, 5, 6), List.of(7, 8, 9));
List<Integer> result = IntStream.range(0, lists.get(0).size())
.boxed()
.flatMap(i -> lists.stream().map(lst->lst.get(i)))
.collect(Collectors.toList());
System.out.println(result);
Une autre solution facile à comprendre:
IntStream.range(0, one.size())
.mapToObj(index -> new int[]{one.get(index), two.get(index), three.get(index)})
.forEach(x -> {System.out.print(x[0] + ", " + x[1] + ", " + x[2] + ", ");});