Reputation: 6741
I have a JSON file containing data in the form:
{
"type":"type1",
"value":"value1",
"param": "param1"
}
{
"type":"type2",
"value":"value2",
"param": "param2"
}
I also have an object like this:
public class TestObject {
private final String value;
private final String param;
public TestObject(String value, String param) {
this.value = value;
this.param = param;
}
}
What I want is to create a Map<String, List<TestObject>>
that contains a list of TestObject
s for each type.
This is what I coded:
Map<String, List<TestObject>> result = jsonFileStream
.map(this::buildTestObject)
.collect(Collectors.groupingBy(line -> JsonPath.read(line, "$.type")));
Where the method buildTestObject
is:
private TestObject buildTestObject(String line) {
return new TestObject(
JsonPath.read(line, "$.value"),
JsonPath.read(line, "$.param"));
}
This does not work because the map()
function returns a TestObject
, so that the collect
function does not work on the JSON String line anymore.
In real life, I cannot add the "type" variable to the TestObject
file, as it is a file from an external library.
How can I group my TestObject
s by the type in the JSON file?
Upvotes: 2
Views: 364
Reputation: 56423
You can also use the toMap
collector to accomplish the task at hand.
Map<String, List<TestObject>> resultSet = jsonFileStream
.collect(Collectors.toMap(line -> JsonPath.read(line, "$.type"),
line -> new ArrayList<>(Collections.singletonList(buildTestObject(line))),
(left, right) -> {
left.addAll(right);
return left;
}
));
Upvotes: 1
Reputation: 37645
In addition to the Stream solution, it's worth pointing out that Java 8 also significantly improved the Map
interface, making this kind of thing
much less painful to achieve with a for
loop than had previously been the case. I am not familiar with the library you are using, but something like this will work (you can always convert a Stream
to an Iterable
).
Map<String, List<TestObject>> map = new HashMap<>();
for (String line : lines) {
map.computeIfAbsent(JsonPath.read(line, "$.type"), k -> new ArrayList<>())
.add(buildTestObject(line));
}
Upvotes: 0
Reputation: 33865
You can move the mapping operation to a down stream collector of groupingBy:
Map<String, List<TestObject>> result = jsonFileStream
.collect(Collectors.groupingBy(line -> JsonPath.read(line, "$.type"),
Collectors.mapping(this::buildTestObject, Collectors.toList())));
This will preserve the string so you can extract the type as a classifier, and applies the mapping to the elements of the resulting groups.
Upvotes: 4