2016-12-13 34 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"]} 

我需要做的是計算所有重複的網址和打印一樣:

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爲String的HashMap中,整數

+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