[Java8][Stream] Comment créer une matrice mélangé !
par
, 02/07/2015 à 16h07 (1336 Affichages)
Bonjour,
@mathieupicard Voulant créer une matrice "random" sans doublon, à poser la question de comment faire la comparaison 1/n. Très probablement pour vérifer que sa valeur n'est pas déjà introduit dans sa matrice.
Voulant proposer une approche différente, je me suis trouver du côté de la fonction Collections.shuffle. L'idée étant d'avoir une liste/matrice sans doublon "ordonnée" et de n'avoir qu'à la mélanger.
Mon code de base ressemblait donc à cela :
La création de la liste initiale n'est pas très propre. Et nos n'avons pas une matrice, mais une liste.
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 int table[] = new int[9]; // Remplissage for (int i = 0; i < table.length; i++) { table[i]=i+1; } // Conversion int[] to List<Integer> using Java 8 API List<Integer> list = IntStream.of(table).boxed().collect(Collectors.toList()); Collections.shuffle(list); //Conversion List<Integer> to int[] using Java 8 API table = list.stream().mapToInt(i -> i).toArray(); // Affichage du résultat System.out.println(Arrays.toString(table));
Du coup, en cherchant un peu sur les streams, j'ai trouvé quelques blogs parlant de "Sampling" (échantillonnage) et via la classe pour faire proposer (avec les imports qui n'étaient pas précisé et un peu de commentaire) :
Note : Les deux billets sources sont très intéressant en eux-même. (En plus d'expliquer le comportement du code)
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 import static java.lang.Math.max; import static java.util.stream.Collectors.toList; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; public class SlidingCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> { private final int size; private final int step; private final int window; private final Queue<T> buffer = new ArrayDeque<>(); private int totalIn = 0; /** * @param size Size of a group */ public SlidingCollector(int size) { this(size,size); } /** * @param size Size of a group * @param step number of element betwin each group */ public SlidingCollector(int size, int step) { this.size = size; this.step = step; this.window = max(size, step); } @Override public Supplier<List<List<T>>> supplier() { return ArrayList::new; } @Override public BiConsumer<List<List<T>>, T> accumulator() { return (lists, t) -> { buffer.offer(t); ++totalIn; if (buffer.size() == window) { dumpCurrent(lists); shiftBy(step); } }; } @Override public Function<List<List<T>>, List<List<T>>> finisher() { return lists -> { if (!buffer.isEmpty()) { final int totalOut = estimateTotalOut(); if (totalOut > lists.size()) { dumpCurrent(lists); } } return lists; }; } private int estimateTotalOut() { return max(0, (totalIn + step - size - 1) / step) + 1; } private void dumpCurrent(List<List<T>> lists) { final List<T> batch = buffer.stream().limit(size).collect(toList()); lists.add(batch); } private void shiftBy(int by) { for (int i = 0; i < by; i++) { buffer.remove(); } } @Override public BinaryOperator<List<List<T>>> combiner() { return (l1, l2) -> { throw new UnsupportedOperationException("Combining not possible"); }; } @Override public Set<Characteristics> characteristics() { return EnumSet.noneOf(Characteristics.class); } }l'a
Notre génération de matrice "random" devient beaucoup plus simple d'écriture :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 List<Integer> list = IntStream.range(1, 10).boxed().collect(Collectors.toList()); Collections.shuffle(list); List<List<Integer>> listofList=list.stream().collect(new SlidingCollector<Integer>(3)); int[][] test = listofList.stream().map(i -> i.stream().mapToInt(e -> e).toArray()).toArray(size -> new int[size][]); System.out.println(Arrays.deepToString(test));
Au final on se retrouve avec le code suivante :
Note : J'ai bien galéré sur la transformation de liste de liste en matrice d'entier primitif. Mais, c'est formateur !
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 // On crée uine liste de 1 à 9 List<Integer> list = IntStream.range(1, 10).boxed().collect(Collectors.toList()); // On mélange la liste Collections.shuffle(list); // On divise la liste en groupe de 3 (taille des lignes) List<List<Integer>> listofList=list.stream().collect(new SlidingCollector<Integer>(3)); // On transforme le tout en une matrice int[][] test = listofList.stream().map(i -> i.stream().mapToInt(j -> j).toArray()).toArray(size -> new int[size][]); // i correspond à un élémént de type List<Integer> // j correspond à un élémént de type Integer System.out.println(Arrays.deepToString(test));
Le résultat final étant :
En espérant, que cela serve.Envoyé par Sortie Console
Cordialement,
Patrick Kolodziejczyk.
source :
http://java.dzone.com/articles/group...g-and-batching
http://www.nurkiewicz.com/2014/07/gr...ng-custom.html