将一个集合分成两个不同集合的最佳方法是什么?
What is the best way to divide a collection into 2 different collections?
我有一组数字:
Set<Integer> mySet = [ 1,2,3,4,5,6,7,8,9]
我想分成2组赔率和偶数
我的方法是使用过滤器两次 :
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())
我不喜欢这个解决方案,因为我检查了整个集合两次。
有什么更聪明的方法吗?
简单的循环和if/else将是一个干净简单的解决方案
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);
}
或者使用 ternary operator 可以很好地进一步简化代码
for(Integer val : mySet) {
((val % 2 == 0) ? setEven : setOdd).add(val);
}
您可以使用 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);
}
您可以像下面那样使用 Collectors#partitioningBy
。
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));
Map<Boolean, List<Integer>> partitioned =
set.stream().collect(Collectors.partitioningBy(x -> x%2 == 0));
partitioned.get(true)
中的元素是偶数; partitioned.get(false)
中的元素是奇数。
与使用 groupingBy
不同,它保证 true
和 false
列表都将出现在地图中,即使它们是空的。 (Java 8 中没有记录,但确实如此;Java 9 的文档现在明确说明了这一点)。
您可以使用 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);
编辑:
我看到有几个相似的答案。这里的细微差别是它显示了如何将集合作为 Set
而不是 List 以防 OP 想要那样。
如果您已经有集合来保存值,下面可以作为解决方案。
data.stream().forEach(x -> {
if(x%2==0){
//add to collection holding even nums
} else {
//add to collection holding odd nums
}
})
我有一组数字:
Set<Integer> mySet = [ 1,2,3,4,5,6,7,8,9]
我想分成2组赔率和偶数
我的方法是使用过滤器两次 :
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())
我不喜欢这个解决方案,因为我检查了整个集合两次。
有什么更聪明的方法吗?
简单的循环和if/else将是一个干净简单的解决方案
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);
}
或者使用 ternary operator 可以很好地进一步简化代码
for(Integer val : mySet) {
((val % 2 == 0) ? setEven : setOdd).add(val);
}
您可以使用 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);
}
您可以像下面那样使用 Collectors#partitioningBy
。
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));
Map<Boolean, List<Integer>> partitioned =
set.stream().collect(Collectors.partitioningBy(x -> x%2 == 0));
partitioned.get(true)
中的元素是偶数; partitioned.get(false)
中的元素是奇数。
与使用 groupingBy
不同,它保证 true
和 false
列表都将出现在地图中,即使它们是空的。 (Java 8 中没有记录,但确实如此;Java 9 的文档现在明确说明了这一点)。
您可以使用 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);
编辑:
我看到有几个相似的答案。这里的细微差别是它显示了如何将集合作为 Set
而不是 List 以防 OP 想要那样。
如果您已经有集合来保存值,下面可以作为解决方案。
data.stream().forEach(x -> {
if(x%2==0){
//add to collection holding even nums
} else {
//add to collection holding odd nums
}
})