Java 8 Streams считает все ключи

У меня есть файл, который содержит данные в форме формата JSON. Я читаю это построчно, и каждая строка имеет 1 запись JSON, поэтому формат не является проблемой. Ниже приведен пример строки:

{"url": "http://ldrlongdistancerider.com/bikers_rights_motorcycle/rightsriders0163.php", "timestamp": 1257072412, "tags": ["nscensorship", "cloudmark", "network", "solutions", "content", "based", "spam", "signatures"]}

Что мне нужно сделать, так это сосчитать все дубликаты URL и напечатать их следующим образом:

 http://ldrlongdistancerider.com/bikers_rights_motorcycle/rightsriders0163.php"  1

Как я могу добиться этого с помощью потоков? Кстати, мне нужно отфильтровать записи на основе отметки времени. Поэтому, если кто-то пропустит диапазон дат, мне придется подсчитать URL-адреса, попадающие в этот диапазон. Я сделал большую часть этого, но эта счетная часть сбивает меня с толку.

Вот что я сделал до сих пор:

for (Path filePath : files) {
        try {
            Files.lines(Paths.get(filePath.toUri()))
                 .filter(s -> Link.parse(s).timestamp() > startSeconds)
                 .filter(s -> Link.parse(s).timestamp() < stopSeconds)
                 .forEach(s -> countMap.put(Link.parse(s).url(), 1));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

countMap - это HashMap из String, Integer

2 ответа

Решение

Вы анализируете несколько раз и изменяете внешнюю карту, вместо того, чтобы позволить потоку создавать карту для вас, что является анти-паттерном (затрудняет параллельный поток)

Вы могли бы просто использовать

Files.lines(Paths.get(filePath.toUri()))
     .map(Link::parse)
     .filter(link -> link.timestamp() > startSeconds && link.timestamp() < stopSeconds)
     .collect(Collectors.groupingBy(Link::url, Collectors.counting()));
countMap = Files.lines(Paths.get(filePath.toUri()))
                 .filter(s -> Link.parse(s).timestamp() > startSeconds)
                 .filter(s -> Link.parse(s).timestamp() < stopSeconds)
                 .collect(Collectors.groupingBy(x ->Link.parse(x).url()))
                 .entrySet()
                 .stream()
                 .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().size()));

Это то, что я в итоге сделал, и это работает. Да, мне нужно было поработать над проблемой синтаксического анализа @JB Nizet

Другие вопросы по тегам