从Java 8中的方法返回List <integer>?

时间:2018-11-14 14:32:34

标签: 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) {
        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;
}

4 个答案:

答案 0 :(得分:8)

看起来您只需要元素的总和即可检查它是奇数还是偶数。要知道这一点,只需检查奇数元素的数量是奇数还是偶数即可。

您可以将输入拆分为奇数和偶数列表,并根据奇数List的大小决定要返回哪个:

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
}

测试:

System.out.println (oddOrEven(Arrays.asList (1,2,3,4,5)));
System.out.println (oddOrEven(Arrays.asList (1,2,3,4,5,3)));

输出:

[1, 3, 5]
[2, 4]

编辑:

在我的原始答案中,我错过了distinct()步骤,该步骤应在我们决定是返回奇数元素还是偶数元素之后恐怕这需要添加第二条Stream管道:

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());
}

或(根据Holger的建议):

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());
}

答案 1 :(得分:2)

 long sum = integers.stream().reduce(0, (u, v) -> u + v);
 return integers.stream().filter(x -> (x % 2)==(sum % 2)).distinct().collect(Collectors.toList());

答案 2 :(得分:1)

我将为您提供一个更简单的解决方案,该解决方案使用标准Java语言构造而不创建流创建的其他寄生对象。我不是说信息流不好。我的意思是,如果您将List传递给方法并返回List,则要流式转换并收集回list的转换是您不需要的额外工作,您也不应该这样做。您可以尝试将其用于教育目的和学习流,但是在这种特殊情况下,您会失去性能,如果在实际应用程序中的任何地方都开始这样做,它将加起来,并且可能会成为严重的问题。即使过早的优化不是一件好事,也可以说使用流执行所有操作只是因为它们是Java语言,根本不关心性能。

如果我们有偶数个奇数,那么总和也是偶数。因此,这是一些按位运算符的代码(只是为了好玩-您可以使用标准i%2等编写它):

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
}

您可以针对其他基于Stream的解决方案进行测试。在大多数情况下,使用标准Java构造而不带来额外的负担的解决方案将是相同的速度或更快的速度。例如,使用map很好,但列表较大,在某些点上有很多重复的数字,那么碰撞的数量会使它慢得多,比其他方法慢很多倍。所有算法的复杂度都是线性的,但是一次迭代的工作量会随流解决方案(以及传统方法)的不同而变化,如果一个人不知道损失了什么,那么可能会坚持使用众所周知的算法。容易预测的场景会更好。

答案 3 :(得分:0)

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);
}