Reputation: 67
Hello fellow soldiers.
Obviously keys in hashmaps are unique. However, I've been trying to write a code that reads a csv file and then puts the key and value in the map. However, there are keys the same (every key is like 15 times in the csv file). In that case, it should make a sum of the values, and just return the key once. How to do that? My code right now is as follows.
BufferedReader br = null;
String line;
try {
br = new BufferedReader(new FileReader(filepath));
} catch (FileNotFoundException fnfex) {
System.out.println(fnfex.getMessage() + "Bestand niet gevonden!");
System.exit(0);
}
//this is where we read lines
try {
while((line = br.readLine()) != null) {
String[] splitter = line.split(cvsSplitBy);
if(splitter[0] != "Voertuig") {
alldataMap.put(splitter[0], splitter[8]);
}
//MIGHT BE JUNK, DONT KNOW YET
/*if((splitter[0].toLowerCase()).contains("1")){
double valuekm = Double.parseDouble(splitter[8]);
license1 += valuekm;
System.out.println(license1);
}
else {
System.out.println("not found");
}*/
}
System.out.println(alldataMap);
TextOutput();
} catch (IOException ioex) {
System.out.println(ioex.getMessage() + " Error 1");
} finally {
System.exit(0);
}
So if I have the following info (in this case its the 0th and 8th word read every line in the csv file)
Apples; 299,9
Bananas; 300,23
Apples; 3912,1
Bananas;342
Bananas;343
It should return
Apples;Total
Bananas;Total
Upvotes: 0
Views: 382
Reputation: 54168
I won't suggest the way to it in a loop because that's already done, but I'd suggest a Streams
solution, in a unique line :
Map<String, Double> alldataMap = new HashMap<>();
try {
alldataMap =
Files.lines(Paths.get("", filepath))
.map(str -> str.split(cvsSplitBy))
.filter(splitte -> !splitte[0].equals("Voertuig"))
.collect(Collectors.toMap(sp -> sp[0],
sp -> Double.parseDouble(sp[8].replaceAll(",", ".")),
(i1, i2) -> i1 + i2));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(alldataMap); // {Apples=4212.0, Bananas=985.23}
The steps are the same :
cvsSplitBy
Voertuig
(! use .equals()
and not !=
)String
String
parsed as Double
Edit, as nobody propose the use of .getOrDefault()
I give it
while ((line = br.readLine()) != null) {
String[] splitter = line.split(cvsSplitBy);
if (!splitter[0].equals("Voertuig")) {
alldataMap.put(splitter[0],
alldataMap.getOrDefault(splitter[0], 0.0) +
Double.parseDouble(splitter[8].replaceAll(",", ".")));
}
}
If tke key already exists, it'll sum, it the key does not exists it'll sum the value with a 0
Upvotes: 1
Reputation: 2937
Try the following:
if( alldataMap.containsKey(splitter[0]) ) {
Double sum = alldataMap.remove(splitter[0]) + Double.parseDouble(splitter[8]);
allDataMap.put(splitter[0], sum );
} else {
alldataMap.put(splitter[0], Double.valueOf(splitter[8]) );
}
Upvotes: 3
Reputation: 1205
i would use the merge
for a map :
alldataMap.merge(splitter[0], Double.valueOf(splitter[8]), (oldVal, newVal) -> oldVal + newVal);
From doc:
If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value. Otherwise, replaces the associated value with the results of the given remapping function, or removes if the result is null. This method may be of use when combining multiple mapped values for a key. For example, to either create or append a String msg to a value mapping:
Upvotes: 1
Reputation: 44250
You can use putIfAbsent
and compute
since Java 8:
Map<String, Integer> myMap = new HashMap<>();
//...
String fruitName = /*whatever*/;
int qty = /*whatever*/;
myMap.putIfAbsent(fruitName, 0);
myMap.compute(fruitName, (k, oldQty) -> oldQty + qty);
Upvotes: 2
Reputation: 3040
You can use Map#containsKey()
to check for an existing mapping, then if there is one use Map#get()
to retrieve the value and add the new one, and finally Map#put()
to store the sum:
if(map.containsKey(key))
map.put(key, map.get(key)+value);
else
map.put(key, value);
See here for the documentation of those methods.
Upvotes: 1