J'ai un ensemble de chiffres:
Set<Integer> mySet = [ 1,2,3,4,5,6,7,8,9]
Je veux le diviser en 2 ensembles de cotes et d'unités.
Ma façon était d'utiliser le filtre deux fois:
Set<Integer> set1 = mySet.stream().filter(y -> y % 2 == 0).collect(Collectors.toSet())
Set<Integer> set2 =mySet.stream().filter(y -> y % 2 != 0).collect(Collectors.toSet())
Je n'aime pas cette solution car je passe deux fois sur l'ensemble.
Existe-t-il un moyen plus intelligent de le faire?
Map<Boolean, List<Integer>> partitioned =
set.stream().collect(Collectors.partitioningBy(x -> x%2 == 0));
Les éléments de partitioned.get(true)
sont pairs; les éléments dans partitioned.get(false)
sont impairs.
Contrairement à cela en utilisant groupingBy
, il est garanti que les listes true
et false
seront présentes dans la carte même si elles sont vides. (Non documenté dans Java 8, mais c'était vrai; Java 9 l'indique maintenant explicitement).
Boucle simple et si/sinon serait une solution propre et simple
Set<Integer> setEven = new HashSet<>();
Set<Integer> setOdd = new HashSet<>();
for (Integer val : mySet) {
if (val % 2 == 0)
setEven.add(val);
else
setOdd.add(val);
}
Ou utiliser un opérateur ternaire fonctionne bien pour simplifier encore plus le code
for(Integer val : mySet) {
((val % 2 == 0) ? setEven : setOdd).add(val);
}
Vous pouvez utiliser Collectors#partitioningBy
comme ci-dessous.
Map<Boolean,List<Integer>> evenOddMap = mySet.stream().collect(Collectors.partitioningBy(e -> e % 2 == 0));
System.out.println("Even : "+evenOddMap.get(true));
System.out.println("Odd : "+evenOddMap.get(false));
Vous pouvez utiliser Collectors.partitioningBy :
Map< Boolean, Set<Integer> > map =
mySet.stream().collect( Collectors.partitioningBy( y -> y % 2 == 0,
Collectors.toSet() ) );
Set<Integer> odds = map.get(Boolean.TRUE);
Set<Integer> evens = map.get(Boolean.FALSE);
MODIFIER:
Je vois qu'il y a quelques réponses similaires. La légère différence ici est qu'elle montre comment obtenir les collections en tant que Set
au lieu de List au cas où OP le souhaiterait de cette façon.
Si vous disposez déjà de collections pour contenir des valeurs, ce qui suit peut être une solution.
data.stream().forEach(x -> {
if(x%2==0){
//add to collection holding even nums
} else {
//add to collection holding odd nums
}
})
Vous pouvez utiliser un groupingBy
public void test(String[] args) {
Integer[] test = {1,2,3,4,5,6,7,8,9};
Map<Integer, List<Integer>> evenOdd = Arrays.stream(test).collect(Collectors.groupingBy(i -> i & 1));
Set<Integer> evens = new HashSet<>(evenOdd.get(0));
Set<Integer> odds = new HashSet<>(evenOdd.get(1));
System.out.println("Evens "+evens+" Odds "+odds);
}