代码之家  ›  专栏  ›  技术社区  ›  Saikat SHASHANK HONRAO

使用Java函数式编程简化if-else条件

  •  2
  • Saikat SHASHANK HONRAO  · 技术社区  · 7 年前

    有没有建议使用Java8特性简化以下代码块?

    int[] ans = new int[2];
    list.forEach(i -> {
        if (i > 0) {
            ans[0] += 1;
        } else if (i < 0) {
            ans[1] += 1;
        }
    });
    

    顺便说一句,我不知道我是否应该把这个贴出来 here

    5 回复  |  直到 7 年前
        1
  •  4
  •   Leo Aso    7 年前

    如果您不想计算零,那么您的代码就非常简单。如果你想把零算作正数,那么你可以把它缩短成这个。

    int[] ans = new int[2];
    for (int i : list) ans[i < 0 ? 1 : 0] += 1;
    
        2
  •  2
  •   Eugene    7 年前
     ans[0] = (int)list.stream().filter(x -> x < 0).count();
     ans[1] = (int)list.stream().filter(x -> x > 0).count();
    

    但我不认为这是一个简单的问题,你的解决方案已经很简单了。

    如果确实要计算零,可以简化为:

     list.forEach(x -> ++ans[x >>> 31])
    
        3
  •  1
  •   maaartinus    7 年前

    我建议你

    int[] ans = new int[2];
    list.forEach(i -> ans[i >>> 31] += i==0 ? 0 : 1);
    

    哪里 i >>> 31 丢弃除符号位以外的所有位(即,与 i<0 ? 1 : 0 )第二个条件处理零。

    我不主张,它真的比原来的好。

        4
  •  1
  •   LuCio    7 年前

    区分两种情况 i > 0 i < 0 我们可以用 Stream.partition :

    Map<Boolean, List<Integer>> partitioned = list.stream()
      .filter(i -> i != 0)
      .collect(Collectors.partitioningBy(i -> i > 0));
    ans[0] = partitioned.get(true).size();
    ans[1] = partitioned.get(false).size();
    

    它简化了吗?至少它仍然易读易懂。


    或者如@saka1029所示:

    Map<Boolean, Long> partitioned = list.stream()
      .filter(i -> i != 0)
      .collect(Collectors.partitioningBy(i -> i > 0, Collectors.counting()));
    ans[0] = partitioned.get(true);
    ans[1] = partitioned.get(false);
    

    编辑
    更进一步 Stream

    int[] ans = list.stream().filter(i -> i != 0).collect(
      () -> new int[2], 
      (arr, i) -> arr[i > 0 ? 0 : 1]++, 
      (l, r) -> {  l[0] += r[0]; l[1] += r[1]; });
    
        5
  •  0
  •   fps    7 年前

    int[] ans = new int[3];
    list.forEach(i -> ans[Integer.signum(i) + 1] += 1);
    

    这个 ans

    [1, 2, 3, 0, -4, -5] ,输出为: [2, 1, 3] .


    更实用的方法,不包括零:

    Map<Integer, Long> bySignum = list.stream()
        .filter(i -> i != 0)
        .collect(Collectors.groupingBy(Integer::signum, Collectors.counting()));
    

    {-1=2, 1=3} .