Есть ли способ объединить повторяющиеся числа в списке, используя потоки в Java 8? - PullRequest
7 голосов
/ 06 марта 2020

например # 1 [1, 1, 1, 2, 22, 35, 35, 120, 320] == >> [3, 2, 22, 70, 120, 320]

обратите внимание, как повторяющиеся последовательные 1 и 35 объединяются в 3 и 70 соответственно

например # 2 [1,1,3,1,1] == >> [2,3,2]

Ответы [ 3 ]

9 голосов
/ 06 марта 2020
Stream.of(1, 1, 1, 2, 22, 35, 35, 120, 320)
          .collect(Collectors.toMap(
              Function.identity(),
              Function.identity(),
              Integer::sum,
              LinkedHashMap::new
          ))
          .values()
          .forEach(System.out::println);

В случае, если вы разместили комментарий, вам понадобится пользовательский коллектор, фактически:

static class Custom implements Collector<Integer, List<Integer>, List<Integer>> {

    private Integer match;

    @Override
    public Supplier<List<Integer>> supplier() {
        return ArrayList::new;
    }

    @Override
    public BiConsumer<List<Integer>, Integer> accumulator() {
        return (list, x) -> {
            int lastIndex = list.size() - 1;
            if (match != null && match.equals(x)) {
                list.set(lastIndex, list.get(lastIndex) + x);
            } else {
                match = x;
                list.add(x);
            }
        };
    }

    @Override
    public BinaryOperator<List<Integer>> combiner() {
        return (left, right) -> {
            throw new RuntimeException("Not for parallel");
        };
    }

    @Override
    public Function<List<Integer>, List<Integer>> finisher() {
        return Function.identity();
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Set.of();
    }
}

И использование будет:

public static void main(String[] args) {
    Stream.of(1, 1, 3, 1, 1)
          .collect(new Custom())
          .forEach(System.out::println);
}
4 голосов
/ 06 марта 2020

Зачем использовать потоки, если вы можете сделать это с простым для l oop и блоком if-else?

   List<Integer> list = List.of(0, 0, 0, 0, 1, 1, 1, 0, 0, 0);
   List<Integer> result = new ArrayList<>();
   Integer curr = list.get(0);
   Integer sum = 0;
   for(Integer i : list){
       if(i.equals(curr)){
           sum += i;
       }
       else{
           result.add(sum);
           sum = i;
           curr = i;
       }
   }
   result.add(sum);
   System.out.println(result);
1 голос
/ 08 марта 2020

Вот подход с использованием стека.

public static List<Integer> coalesce(List<Integer> list) {
    Stack<Integer> stack = new Stack<>();
    stack.addAll(list);
    List<Integer> sums = new ArrayList<>();
    int sum = 0;
    while (!stack.isEmpty()) {
       int val = stack.pop();
       sum += val;
       if (!stack.isEmpty() && stack.peek() != val) {
          sums.add(0,sum);
          sum = 0;
       }
    }
    sums.add(0,sum);
    return sums;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...