如果总和为奇数,则使用一个流从列表中删除奇数整数,如果总和为偶数,则删除偶数整数
Using one stream delete from a list odd integers if their sum is odd, delete even integers if the sum is even
我需要实现一个方法oddOrEven(List<Integer> integers)
:如果整数值之和为奇数,该方法应删除所有奇数元素,如果总和为偶数,该方法应删除所有偶数。
任务是实现一个时间复杂度为O(N)
的方法。我可以使用局部变量,但我应该只写一个流。
这是我的两个流的解决方案。
private static List<Integer> oddOrEven(List<Integer> integers) {
Integer sum = integers.stream().reduce(0, Integer::sum);
return integers.stream().filter((a) -> sum % 2 == 0 && a % 2 != 0 ||
sum % 2 != 0 && a % 2 == 0)
.collect(toList());
}
我还尝试计算流内的总和,但这不起作用,因为 sum.value 在 List<Integer>
整数值的迭代过程中发生变化。
private static List<Integer> oddOrEven3(List<Integer> integers) {
class IntegerWrapper {
private int value = 0;
}
final IntegerWrapper sum = new IntegerWrapper();
return integers.stream()
.peek((a) -> sum.value += a)
.filter((a) -> {
return sum.value % 2 == 0 && a % 2 != 0 ||
sum.value % 2 != 0 && a % 2 == 0;
})
.collect(toList());
}
请帮我弄清楚如何只用一个流来解决任务?有没有办法在流中存储在迭代期间不改变的总和?
这是一个解决方案
private static List<Integer> oddOrEven(List<Integer> integers) {
final Map<Boolean, List<Integer>> oddsAndEvens = integers.stream()
.collect(Collectors.partitioningBy(i -> i % 2 == 0));
return oddsAndEvens.get(oddsAndEvens.get(false).size() % 2 != 0);
}
它的工作原理是将列表分成 2 个列表,奇数和偶数。然后它通过查看赔率列表的大小来选择要 return 的列表。
这是一种可能。
- 使用发球收集器创建两个列表,一个是奇数,一个是偶数
- 然后 return 根据奇数的计数得出适当的列表。这是有效的,因为偶数的赔率总和为偶数,而奇数的总和为奇数。偶数总归偶数。
public List<Integer> oddOrEven(List<Integer> values) {
return values.stream().collect(Collectors.teeing(
Collectors.filtering(i -> i % 2 == 0,
Collectors.toList()),
Collectors.filtering(i -> i % 2 == 1,
Collectors.toList()),
(even, odd) -> odd.size() % 2 == 1 ? even : odd));
}
这是 @hulk 在评论中建议的另一种解决方案。我选择不使用 partitioningBy
而是 groupingBy
.
public List<Integer> oddOrEven(List<Integer> values) {
return values.stream()
.collect(collectingAndThen(
Collectors.groupingBy(i -> i % 2),
map -> map.getOrDefault(
(map.getOrDefault(1, List.of()).size() + 1)
% 2,
List.of())));
}
finisher
和以前一样,检查奇数列表(map.get(1))
的大小。 return other list
基于赔率的大小,将 1
添加到该大小,然后得到除以 2
.
的余数
感谢 @Holger 建议使用 map.getOrDefault()
来处理最终映射中缺少的键。
我需要实现一个方法oddOrEven(List<Integer> integers)
:如果整数值之和为奇数,该方法应删除所有奇数元素,如果总和为偶数,该方法应删除所有偶数。
任务是实现一个时间复杂度为O(N)
的方法。我可以使用局部变量,但我应该只写一个流。
这是我的两个流的解决方案。
private static List<Integer> oddOrEven(List<Integer> integers) {
Integer sum = integers.stream().reduce(0, Integer::sum);
return integers.stream().filter((a) -> sum % 2 == 0 && a % 2 != 0 ||
sum % 2 != 0 && a % 2 == 0)
.collect(toList());
}
我还尝试计算流内的总和,但这不起作用,因为 sum.value 在 List<Integer>
整数值的迭代过程中发生变化。
private static List<Integer> oddOrEven3(List<Integer> integers) {
class IntegerWrapper {
private int value = 0;
}
final IntegerWrapper sum = new IntegerWrapper();
return integers.stream()
.peek((a) -> sum.value += a)
.filter((a) -> {
return sum.value % 2 == 0 && a % 2 != 0 ||
sum.value % 2 != 0 && a % 2 == 0;
})
.collect(toList());
}
请帮我弄清楚如何只用一个流来解决任务?有没有办法在流中存储在迭代期间不改变的总和?
这是一个解决方案
private static List<Integer> oddOrEven(List<Integer> integers) {
final Map<Boolean, List<Integer>> oddsAndEvens = integers.stream()
.collect(Collectors.partitioningBy(i -> i % 2 == 0));
return oddsAndEvens.get(oddsAndEvens.get(false).size() % 2 != 0);
}
它的工作原理是将列表分成 2 个列表,奇数和偶数。然后它通过查看赔率列表的大小来选择要 return 的列表。
这是一种可能。
- 使用发球收集器创建两个列表,一个是奇数,一个是偶数
- 然后 return 根据奇数的计数得出适当的列表。这是有效的,因为偶数的赔率总和为偶数,而奇数的总和为奇数。偶数总归偶数。
public List<Integer> oddOrEven(List<Integer> values) {
return values.stream().collect(Collectors.teeing(
Collectors.filtering(i -> i % 2 == 0,
Collectors.toList()),
Collectors.filtering(i -> i % 2 == 1,
Collectors.toList()),
(even, odd) -> odd.size() % 2 == 1 ? even : odd));
}
这是 @hulk 在评论中建议的另一种解决方案。我选择不使用 partitioningBy
而是 groupingBy
.
public List<Integer> oddOrEven(List<Integer> values) {
return values.stream()
.collect(collectingAndThen(
Collectors.groupingBy(i -> i % 2),
map -> map.getOrDefault(
(map.getOrDefault(1, List.of()).size() + 1)
% 2,
List.of())));
}
finisher
和以前一样,检查奇数列表(map.get(1))
的大小。 return other list
基于赔率的大小,将 1
添加到该大小,然后得到除以 2
.
感谢 @Holger 建议使用 map.getOrDefault()
来处理最终映射中缺少的键。