问题
I am currently learning a bit about streams. I have the following JSONArray, and I want to be able to retrieve all the distinct xvalues.
datasets: {
ds1: {
xvalues: [
"(empty)",
"x1",
"x2"
]
},
ds2: {
xvalues: [
"(empty)",
"x1",
"x2",
"x3"
]
}
}
I am trying the following code but it doesn't seem quite right....
List<String> xvalues = arrayToStream(datasets)
.map(JSONObject.class::cast)
.map(dataset -> {
try {
return dataset.getJSONArray("xvalues");
} catch (JSONException ex) {
}
return;
})
.distinct()
.collect((Collectors.toList()));
private static Stream<Object> arrayToStream(JSONArray array) {
return StreamSupport.stream(array.spliterator(), false);
}
回答1:
I believe using a json library(Jackson, Gson) is the best way to deal with json data. If you can use Jackson, this could be a solution
public class DataSetsWrapper {
private Map<String, XValue> datasets;
//Getters, Setters
}
public class XValue {
private List<String> xvalues;
//Getters, Setters
}
ObjectMapper objectMapper = new ObjectMapper();
DataSetsWrapper dataSetsWrapper = objectMapper.readValue(jsonString, DataSetsWrapper.class);
List<String> distinctXValues = dataSetsWrapper.getDatasets()
.values()
.stream()
.map(XValue::getXvalues)
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
Replace jsonString with your json. I tested this with this json
String jsonString = "{\"datasets\": {\n" +
" \"ds1\": {\n" +
" \"xvalues\": [\n" +
" \"(empty)\",\n" +
" \"x1\",\n" +
" \"x2\"\n" +
" ]\n" +
" },\n" +
" \"ds2\": {\n" +
" \"xvalues\": [\n" +
" \"(empty)\",\n" +
" \"x1\",\n" +
" \"x2\",\n" +
" \"x3\"\n" +
" ]\n" +
" }\n" +
"}}";
回答2:
What you get with .map(dataset -> dataset.getJSONArray("xvalues")
(try-catch
block omitted for sake of clarity) is a list itself and the subsequent call of distinct
is used on the Stream<List<Object>>
checking whether the lists itself with all its content is same to another and leave distinct lists.
You need to flat map the structure to Stream<Object>
and then use the distinct
to get the unique items. However, first, you need to convert JSONArray to List.
List<String> xvalues = arrayToStream(datasets)
.map(JSONObject.class::cast)
.map(dataset -> dataset -> {
try { return dataset.getJSONArray("xvalues"); }
catch (JSONException ex) {}
return;})
.map(jsonArray -> toJsonArray(jsonArray )) // convert it to List
.flatMap(List::stream) // to Stream<Object>
.distinct()
.collect(Collectors.toList());
来源:https://stackoverflow.com/questions/58261053/how-to-get-all-the-distinct-values-by-key-inside-stream-java8