How to get all the distinct values by key inside stream java8

别等时光非礼了梦想. 提交于 2019-12-30 10:49:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!