2016-12-13 4 views
2

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

{"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 Строки, Integer

+1

Вы можете использовать 'map (Link :: parse)', чтобы избежать синтаксического анализа всего три раза. – Bubletan

+0

Я не могу, так как мне нужно отфильтровать URL-адреса на основе первой отметки времени. Использование ссылки на метод не даст мне то, что мне нужно. – Bytekoder

ответ

4

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

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

Files.lines(Paths.get(filePath.toUri())) 
    .map(Link::parse) 
    .filter(link -> link.timestamp() > startSeconds && link.timestamp() < stopSeconds) 
    .collect(Collectors.groupingBy(Link::url, Collectors.counting())); 
0
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

Смежные вопросы