разделить список на подсписки, сгруппировав ** только ** повторяющиеся элементы, которые находятся рядом друг с другом - PullRequest
2 голосов
/ 06 марта 2020

Есть ли простой способ разбить список на подсписки, сгруппировав только повторяющихся элементов, которые смежны друг с другом?

Простой пример со следующим списком строк:

Input:  [RED,RED,BLUE,BLUE,BLUE,GREEN,BLUE,BLUE,RED,RED]

Output:  [[RED,RED],[BLUE,BLUE,BLUE],[GREEN],[BLUE,BLUE],[RED,RED]]

Если я использую groupingBy из потоков java, все равные элементы окажутся в одном и том же подсписке, чего я хочу избежать. Есть идеи?

Ответы [ 2 ]

3 голосов
/ 06 марта 2020

Вы можете создать собственный коллектор:

List<String> input = Arrays.asList("RED", "RED", "BLUE", "BLUE", "BLUE", "BLUE", "RED", "RED");
List<List<String>> output = input.stream()
                                  .collect(Collector.of(ArrayList::new, (accumulator, item) ->
                                  {
                                      if(accumulator.isEmpty())
                                      {
                                          List<String> list = new ArrayList<>();
                                          list.add(item);
                                          accumulator.add(list);
                                      }
                                      else
                                      {
                                          List<String> last = accumulator.get(accumulator.size() - 1);
                                          if(last.isEmpty() || last.get(0).equals(item)) last.add(item);
                                          else
                                          {
                                              List<String> list = new ArrayList<>();
                                              list.add(item);
                                              accumulator.add(list);
                                          }
                                      }
                                  }, (left, right) -> {left.addAll(right); return left;}));
2 голосов
/ 06 марта 2020

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

List<String> values = Arrays.asList("RED", "RED", "BLUE", "BLUE", "BLUE", "BLUE", "RED", "RED");
    List<List<String>> output = new ArrayList<List<String>>();
    String previous = null;
    List<String> subList = new ArrayList<String>();
    for (String value : values) {
        if (previous == null || value.equals(previous)) {
            subList.add(value);
        } else {
            output.add(subList);
            subList = new ArrayList<String>();
            subList.add(value);
        }
        previous = value;
    }
    if (!subList.isEmpty()) {
        output.add(subList);
    }
    System.out.println(output);
...