Reputation: 20834
I'm writing a Java program that gets data from a CSV file. For each row of data, I need to put each data element into a map using the corresponding header as a key. For example, headerRow[7]
and dataElements[7]
should be a key-value pair in the map.
Below is the code as I would write it traditionally using Java:
private Map<String, Double> readLine(String[] headerRow, String[] dataElements) {
Map<String, Double> headerToDataMap = new HashMap<>();
for (int i=0; i < nextLine.length; i++) {
headerToDataMap.put(headerRow[i], Double.valueOf(dataElements[i]));
}
return headerToDataMap;
}
Is there a way that I can write this code using Java 8 streams, keeping in mind that I'm iterating on two arrays at the same time?
Upvotes: 5
Views: 5416
Reputation: 21409
One solution would be to use a library that provides a method for zipping two streams together. Both the Guava and StreamEx libraries have such methods.
private Map<String, Double> readLine(String[] headerRow, String[] dataElements) {
return Streams.zip(
Arrays.stream(headerRow),
Arrays.stream(dataElements),
(a, b) -> Map.entry(a, Double.valueOf(b)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
private Map<String, Double> readLine(String[] headerRow, String[] dataElements) {
return EntryStream.zip(headerRow, dataElements)
.mapValues(Double::valueOf)
.toMap();
}
or:
private Map<String, Double> readLine(String[] headerRow, String[] dataElements) {
return StreamEx.zip(
headerRow,
dataElements,
(a, b) -> Map.entry(a, Double.valueOf(b)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
Upvotes: 0
Reputation: 4434
You can make something just a little longer using the BiFunction interface.
private Map<String, Double> readLine(String[] headerRow, String[] dataElements) {
Map<String, Double> headerToDataMap = new HashMap<>();
BiFunction<String,String, KeyValue> toKeyValuePair = (s1,s2) -> new KeyValue(s1,s2);
IntStream.range(0, nextLine.length)
.mapToObj(i -> toKeyValuePair.apply(headerRow[i], dataElements[i]) )
.collect(Collectors.toList())
.stream()
.forEach(kv -> {
headerToDataMap.put(kv.getKey(), Double.valueOf(kv.getValue()));
});
return headerToDataMap;
}
The KeyValue type is a simple key value instance generator (code below)
private class KeyValue {
String key;
String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public KeyValue(String key, String value) {
super();
this.key = key;
this.value = value;
}
public KeyValue() {
super();
}
}
Upvotes: 1
Reputation: 198571
The closest thing you can get to this in vanilla Java 8 would probably be
IntStream.range(0, nextLine.length())
.boxed()
.collect(toMap(i -> headerRow[i], i -> dataElements[i]));
Upvotes: 10