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] + ", ");});