Как получить все различные значения по ключу внутри потока java8 - PullRequest
3 голосов
/ 06 октября 2019

В настоящее время я немного изучаю потоки. У меня есть следующий JSONArray, и я хочу иметь возможность получить все различные значения x.

 datasets: {
    ds1: {
     xvalues: [
        "(empty)",
        "x1",
        "x2"
      ]
    },
    ds2: {
    xvalues: [
        "(empty)",
        "x1",
        "x2",
        "x3"
      ]
    }
}

Я пытаюсь следующий код, но он не совсем подходит ....

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);
}

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Я считаю, что использование библиотеки json (Джексон, Gson) - лучший способ работы с данными json. Если вы можете использовать Джексона, это может быть решением

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()); 

Замените jsonString на ваш json. Я проверил это с этим 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" +
        "}}";
0 голосов
/ 06 октября 2019

То, что вы получаете с .map(dataset -> dataset.getJSONArray("xvalues") (блок try-catch опущен для ясности), представляет собой сам список, и последующий вызов distinct используется на Stream<List<Object>>, проверяющем, является ли сам список со всем его содержимымто же самое к другому и оставьте различные списки.

Вам необходимо отобразить структуру на Stream<Object>, а затем использовать distinct, чтобы получить уникальные предметы. Однако сначала вам нужно преобразовать JSONArray в список .

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());
...