[英]Group by and sum operation on a String array
我有一個String[]
dataValues
如下:
ONE:9
TWO:23
THREE:14
FOUR:132
ONE:255
TWO:727
FIVE:3
THREE:196
FOUR:1843
ONE:330
TWO:336
THREE:190
FOUR:3664
我想要總計ONE
, TWO
, THREE
, FOUR
, FIVE
。
所以我創建了一個HashMap
:
Map<String, Integer> totals = new HashMap<String, Integer>();
for(String dataValue : dataValues){
String[] keyVal = dataValue.split(":");
totals.put(keyVal[0], totals.get(keyVal[0]).intValue() + Integer.parseInt(keyVal[1]));
}
但是如果密鑰尚未存在於地圖中,則上面的代碼顯然會拋出異常:
Exception in thread "main" java.lang.NullPointerException
在上面的用例中獲取總數的最佳方法是什么?
您可以獲取給定鍵的值並檢查它是否為空:
for(String dataValue : dataValues){
String[] keyVal = dataValue.split(":");
Integer i = totals.get(keyVal[0]);
if(i == null) {
totals.put(keyVal[0], Integer.parseInt(keyVal[1]));
} else {
totals.put(keyVal[0], i + Integer.parseInt(keyVal[1]));
}
}
在上面的用例中獲取總數的最佳方法是什么?
使用Java 8,您可以使用合並功能
for(String dataValue : dataValues){
String[] keyVal = dataValue.split(":");
totals.merge(keyVal[0], Integer.parseInt(keyVal[1]), Integer::sum);
}
這個功能有什么作用? 讓我們引用一下這個文檔:
如果指定的鍵尚未與值關聯或與null關聯,則將其與給定的非空值關聯。 否則,將相關值替換為給定重映射函數的結果,或者如果結果為null則刪除
所以當你得到它時,如果沒有與鍵相關的值,你只需用keyVal[1]
的int值映射它。 如果已經存在,則需要提供一個函數來決定對兩個值(已映射的值和要映射的值)執行的操作。
在你的情況下你想要求它們,所以這個函數看起來像(a, b) -> a + b
,它可以被方法引用Integer.sum
替換,因為它是一個帶兩個int並返回一個int的函數,所以一個有效的候選人(當然還有你需要的語義)。
從文件中獲取Stream<String>
,將每一行拆分為一個數組,按每個數組的第一個元素(鍵)對每個數組進行分組,將其第二個元素(值)映射到整數並求它們:
import static java.util.stream.Collectors.*; ... Map<String, Integer> map = Files.lines(Paths.get("file")) .map(s -> s.split(":")) .collect(groupingBy(arr -> arr[0], summingInt(arr -> Integer.parseInt(arr[1])));
另一種方法是使用toMap
收集器。
.collect(toMap(arr -> arr[0], arr -> Integer.parseInt(arr[1]), Integer::sum));
從相同的Stream<String[]>
,您可以在一個Map<String, Integer>
收集結果,其中鍵是arr[0]
,值是由arr[1]
保存的int值。 如果您具有相同的鍵,則通過將它們相加來合並值。
兩者都給出了相同的結果,我喜歡第一個結果,因為使用收集器的名稱,它使得意圖清楚,您正在對元素進行分組,但這取決於您選擇。
一開始可能有點難以理解它,但是一旦你掌握了這些(下游)收集器的概念,它就會非常強大。
希望能幫助到你! :)
由於Java 8而不是map.get
您可以使用map.getOrDefault
,如果缺少數據,將返回您定義的默認數據
totals.getOrDefault(keyVal[0], 0).intValue()
這是一個優雅的(編輯:pre Java 8)解決方案:
Integer storedVal = hashMap.get(str);
String str = keyVal[0];
int num = Integer.parseInt(keyVal[1]);
hashMap.put(str, storedVal == null ? num : storedVal + num);
檢查密鑰是否存在。 如果沒有,請使用hold int創建它。
如果密鑰確實存在,則檢索該值並進行數學運算,存儲總和。
這是有效的,因為如果一個鍵已經存在,'put'將覆蓋該值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.