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

时间:2018-10-13 05:29:39

标签: java optimization java-8

是否有使用Java 8功能简化以下代码块的建议?

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

P.S。不确定是否应该发布此here

5 个答案:

答案 0 :(得分:4)

如果您不想计数零,则代码将尽可能简单。如果您想将零视为正数,则可以将其缩短为此。

int[] ans = new int[2];
for (int i : list) ans[i < 0 ? 1 : 0] += 1;

答案 1 :(得分:2)

 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])

答案 2 :(得分:1)

我建议

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

其中i >>> 31丢弃除符号位(即与i<0 ? 1 : 0相同)之外的所有字符,而第二个条件句柄则为零。

我不主张,它确实比原始版本好。

答案 3 :(得分:1)

要区分两种情况,例如i > 0i < 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]; });

答案 4 :(得分:0)

这也是一种计算零的方法:

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

ans数组现在具有3个值:索引0表示负数,索引1表示零数,索引2表示正数。

即对于以下输入:[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}