Сопоставление строкового представления каждой строки с учетом списка списков строк с ее общим числом вхождений - PullRequest
2 голосов
/ 10 июля 2020

Позвольте мне сначала более точно описать задание. Даны следующий класс и внутренний класс:

public class Title {

    private List<Line> lines;

    public Title() {
        this(new ArrayList<>());
    }

    public Title(List<Line> lines) {
        this.lines = lines;
    }

    public void add(Line l) {
        lines.add(l);
    }

    @Override
    public String toString() {
        return lines.toString();
    }

    public List<Line> getLines() {
        return new ArrayList<>(lines);
    }
public  class Line {

    private String line;

    public Line(String line) {
        this.line = line;
    }

    @Override
    public String toString() {
        return line;
    }
}

Предположим, у нас есть List<Title> titles. Задача состоит в том, чтобы получить карту из строкового представления каждой строки с ее общим количеством вхождений в titles. В качестве подсказки указано, что требуется flatMap и что есть решение с Collectors.toMap и одно с Collectors.groupingBy.

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

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.flatMapping;
import static java.util.Collections.frequency;

Map<String, Integer> countsStringMap1 = titles.stream()
                                              .flatMap(t-> t.getLines().stream().map(Line::toString))
                                              .distinct()
                                              .collect(toMap(Function.identity(),
                                                          s -> frequency(titles.stream()
                                                                               .flatMap(t-> t.getLines()
                                                                                             .stream()
                                                                                             .map(Line::toString))
                                                                                             .collect(toList()), s)));

Мне не удалось найти решение с помощью groupingBy, я пробовал комбинацию с Collectors.mapping, но безрезультатно.

Как это можно сделать?

1 Ответ

2 голосов
/ 10 июля 2020

Вы можете использовать counting для подсчета количества вхождений, когда вы groupBy строк по их строковому представлению.

Map<String, Long> countsStringMap = titles.stream()
        .flatMap(t -> t.getLines().stream().map(Title.Line::toString))
        .collect(Collectors.groupingBy(Function.identity(),
                Collectors.counting()));

Обратите внимание, что операция distinct удалена из решения намеренно, поскольку в противном случае у вас остались бы все отдельные строки, прежде чем вы сгруппируете их и в конечном итоге посчитаете каждую из них только один раз.

...