返回列表<;整数>;Java8中的from方法?
我有以下方法(见下文)。代码正在运行,但我得到的提示是有很多重复,我应该使用返回列表<;整数>;Java8中的from方法?,java,java-8,java-stream,Java,Java 8,Java Stream,我有以下方法(见下文)。代码正在运行,但我得到的提示是有很多重复,我应该使用IntStream 您能否指定如何更好地优化代码?提前谢谢 public static List<Integer> oddOrEven(List<Integer> integers) { long sum = integers.stream().mapToInt(i ->i).summaryStatistics().getSum(); if (sum % 2 == 0) {
IntStream
您能否指定如何更好地优化代码?提前谢谢
public static List<Integer> oddOrEven(List<Integer> integers) {
long sum = integers.stream().mapToInt(i ->i).summaryStatistics().getSum();
if (sum % 2 == 0) {
return integers.stream().filter(x -> x % 2==0).distinct().collect(Collectors.toList());
} else if (sum % 2 != 0) {
return integers.stream().filter(x -> x % 2 != 0).distinct().collect(Collectors.toList());
}
return null;
}
公共静态列表oddOrEven(列表整数){
long sum=integers.stream().mapToInt(i->i.summaryStatistics().getSum();
如果(总和%2==0){
返回integers.stream().filter(x->x%2==0.distinct().collect(Collectors.toList());
}否则如果(总和%2!=0){
返回整数.stream().filter(x->x%2!=0).distinct().collect(Collectors.toList());
}
返回null;
}
看起来您只需要元素的总和就可以检查它是奇数还是偶数。要知道这一点,检查奇数元素的数量是奇数还是偶数就足够了
您可以将输入拆分为奇数和偶数列表,并根据奇数列表的大小决定返回哪一个:
public static List<Integer> oddOrEven(List<Integer> integers) {
Map<Boolean,List<Integer>>
oddsAndEvens = integers.stream()
.collect(Collectors.partitioningBy(i->i%2==0));
return oddsAndEvens.get(false).size() % 2 == 0 ? // check if there's an even number of odd
// elements, which means the sum is even
oddsAndEvens.get(true) : // return the even elements
oddsAndEvens.get(false); // return the odd elements
}
输出:
[1, 3, 5]
[2, 4]
编辑:
在我最初的回答中,我错过了distinct()
步骤,该步骤应该在我们决定是否返回奇数或偶数元素之后执行。恐怕这需要添加第二个流
管道:
public static List<Integer> oddOrEven(List<Integer> integers) {
Map<Boolean,List<Integer>>
oddsAndEvens = integers.stream()
.collect(Collectors.partitioningBy(i->i%2==0));
return oddsAndEvens.get(false).size() % 2 == 0 ?
oddsAndEvens.get(true).stream().distinct().collect(Collectors.toList()) :
oddsAndEvens.get(false).stream().distinct().collect(Collectors.toList());
}
公共静态列表oddOrEven(列表整数){
地图
oddsAndEvens=整数。stream()
.collect(收集器.partitionby(i->i%2==0));
返回oddsAndEvens.get(false).size()%2==0?
oddsAndEvens.get(true).stream().distinct().collect(Collectors.toList()):
get(false).stream().distinct().collect(Collectors.toList());
}
或者(根据霍尔格的建议):
公共静态列表oddOrEven(列表整数){
地图
oddsAndEvens=整数。stream()
.collect(收集器.partitionby(i->i%2==0));
返回oddsAndEvens.get(oddsAndEvens.get(false).size()%2==0)
.stream()
.distinct()
.collect(Collectors.toList());
}
公共静态列表oddOrEven(列表整数){
函数fun=i->i%2;
Map Map=integers.stream().collect(Collectors.groupingBy(fun));
返回map.get(1.size()%2==0?map.get(0):map.get(1);
}
我将为您提供一个更简单的解决方案,它使用标准java语言构造,而不创建流所创建的其他寄生虫对象。我不是说溪流不好。我想说的是,如果您将一个列表传递给一个方法并返回一个列表,那么转换为流并收集回列表是额外的工作,您不需要也不应该这样做。您可以出于教育目的尝试它,也可以学习流,但在这种特殊情况下,您只会失去性能,如果您在实际应用程序中的任何地方都这样做,它将累积起来,并可能成为一个重大问题。尽管过早优化不是一件好事,但同样可以说,使用流做任何事情都是因为它们在Java中,根本不关心性能
如果奇数是偶数,那么和也是偶数。下面是一些使用位运算符的代码(只是为了好玩-您可以使用标准i%2等编写):
公共静态集合oddOrEven(列表整数){
int mod=0;
for(整数i:整数){
如果((i&1)=1)模=模^1;
}
Set result=new HashSet();
for(整数i:整数){
如果(((i&1)^mod)==0)
结果.添加(i);
}
return result;//正在转换为set,因为我们需要不同的结果。
//如果顺序很重要,我们可以使用树集或转换为列表
}
您可以对其他基于流的解决方案进行一些测试。在大多数情况下,使用标准java构造而没有额外重载的解决方案将具有相同的速度或更快的速度。例如,使用map很好,但是如果列表较大,在某个点上有大量重复的数字,那么碰撞的数量会使它比其他方法慢很多倍。所有算法的复杂度都是线性的,但一次迭代的工作量会随着不同的流解决方案(以及老式方法)而变化如果你不知道损失是什么,那么坚持众所周知且易于预测的方案可能会更好。关于工作代码的问题属于我。我对IntStream
部分感兴趣。如果你收到一个整数列表,为什么会有人强调它?它更适合于从无到有创建流。您只需使用sum()
而不是.summaryStatistics().getSum()
。此外,如果(总和%2!=0)
已过时,则条件必须为true
。当您删除它时,您可以删除无法访问的returnnull代码>也是。除此之外,您正在使用mapToInt
,因此您正在使用IntStream
。非常感谢。这是一个包裹!)如果列表中包含负数,则此操作无效。例如,尝试使用oddOrEven(Arrays.asList(1,-2))
。是的,需要一个abs()或者像(x&1)=(sum&1)@Floegipoky这样的位检查。我错过了OP代码中的distinct()调用。谢谢你指出这一点。稍后我将修改答案。为什么不返回oddsAndEvens.get(oddsAndEvens.get(false).size()%2==0)
?@Holger nice Improvement因此,您可以使用collector.toSet,也可以使用order Collectors.toCollection(LinkedHashSet::new),而不是收集到要设置的不同项(这将使方法的使用者更容易知道只有不同项)。这只是一个想法;)事实上,你正在变得比线性缩放更好,这表明你的基准是有缺陷的。此外,您正在忽略流解决方案的distinct()
方面,因此结果无论如何都是不可比较的
public static List<Integer> oddOrEven(List<Integer> integers) {
Map<Boolean,List<Integer>>
oddsAndEvens = integers.stream()
.collect(Collectors.partitioningBy(i->i%2==0));
return oddsAndEvens.get(false).size() % 2 == 0 ?
oddsAndEvens.get(true).stream().distinct().collect(Collectors.toList()) :
oddsAndEvens.get(false).stream().distinct().collect(Collectors.toList());
}
public static List<Integer> oddOrEven(List<Integer> integers) {
Map<Boolean,List<Integer>>
oddsAndEvens = integers.stream()
.collect(Collectors.partitioningBy(i->i%2==0));
return oddsAndEvens.get(oddsAndEvens.get(false).size() % 2 == 0)
.stream()
.distinct()
.collect(Collectors.toList());
}
long sum = integers.stream().reduce(0, (u, v) -> u + v);
return integers.stream().filter(x -> (x % 2)==(sum % 2)).distinct().collect(Collectors.toList());
public static List<Integer> oddOrEven(List<Integer> integers) {
Function<Integer, Integer> fun = i -> i%2;
Map<Integer, List<Integer>> map = integers.stream().collect(Collectors.groupingBy(fun));
return map.get(1).size()%2 == 0? map.get(0): map.get(1);
}
public static Collection<Integer> oddOrEven(List<Integer> integers) {
int mod = 0;
for (Integer i : integers) {
if((i & 1) == 1) mod=mod^1;
}
Set<Integer> result = new HashSet<>();
for (Integer i : integers){
if (((i & 1) ^ mod)==0)
result.add(i);
}
return result; //Converting to set because we want distinct results.
// If the order is important we can use treeset or convert to list
}