【问题标题】:How to get all the distinct values by key inside stream java8如何在流java8中通过键获取所有不同的值
【发布时间】:2020-02-04 05:56:18
【问题描述】:

我目前正在学习一些关于流的知识。 我有以下 JSONArray,我希望能够检索所有不同的 xvalue。

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

【问题讨论】:

  • 哪里看起来不太对劲?你能解释一下吗? (也许有一个示例输入和输出。)

标签: java json java-8 java-stream


【解决方案1】:

我相信使用 json 库(Jackson、Gson)是处理 json 数据的最佳方式。如果您可以使用 Jackson,这可能是一个解决方案

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

用你的 json 替换 jsonString。我用这个 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】:

    使用.map(dataset -&gt; dataset.getJSONArray("xvalues")(为清楚起见省略try-catch 块)得到的是一个列表本身,随后对distinct 的调用用于Stream&lt;List&lt;Object&gt;&gt; 检查列表本身及其所有内容是否为与另一个相同,并留下不同的列表。

    您需要将结构平面映射到Stream&lt;Object&gt;,然后使用distinct 来获取唯一项目。但是,首先,您需要转换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());
    

    【讨论】:

    • 在“.flatMap(List::stream)”处,IDE 抱怨“不能在非静态内部调用静态方法”
    • 另外,你能不能提供一个 try, catch 的答案,因为这也给我带来了一些困难。
    • 1) 你不能仅仅删除一段好的代码,因为它看起来很丑(事实上,可能会抛出一个检查异常,所以事情变得有点棘手)2) 你错过了@987654329 @ 3) toJsonArray 是什么? 4) Stream&lt;Object&gt; 看起来不对
    • 我意识到我必须在平面映射之前将JSONArray 转换为List
    • @AndrewTobilko 我删除try-catch 的唯一原因是为了清楚起见。我知道它一定在里面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2016-08-21
    • 2018-11-03
    • 2019-08-10
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    相关资源
    最近更新 更多