Упрощение условия if-else с помощью программирования функциональных стилей Java - PullRequest
0 голосов
/ 13 октября 2018

Любое предложение по упрощению следующего блока кода с использованием функций Java 8?

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

PS Не уверен, стоит ли публиковать здесь здесь

Ответы [ 5 ]

0 голосов
/ 14 октября 2018

Вот способ, который также подсчитывает нули:

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}.

0 голосов
/ 13 октября 2018

Для различения двух случаев, таких как 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]; });
0 голосов
/ 13 октября 2018

Если вы не хотите считать нули, ваш код настолько прост, насколько это возможно.Однако если вы хотите считать нули положительными, вы можете сократить их до этого.

int[] ans = new int[2];
for (int i : list) ans[i < 0 ? 1 : 0] += 1;
0 голосов
/ 13 октября 2018

Я бы предложил

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

, где i >>> 31 отбрасывает все, кроме знакового бита (т. Е. Совпадает с i<0 ? 1 : 0), а вторая условная ручка обрабатывает ноль.

Я не утверждаю, это действительно лучше, чем оригинал.

0 голосов
/ 13 октября 2018
 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])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...