【问题标题】:sorting a json array using java 8 stream api使用 java 8 流 api 对 json 数组进行排序
【发布时间】:2017-12-21 20:56:48
【问题描述】:

我一直在尝试使用 Java 8 的 Stream api 对 JSONArray 进行排序。但是我想我无法正确完成类型转换。

我能得到的只是下面这段代码。,

String objects = "[\n" +
                    "  {\n" +
                    "    \"lat\": \"-16.408545\",\n" +
                    "    \"lon\": \"-71.539105\",\n" +
                    "    \"type\": \"0\",\n" +
                    "    \"distance\": \"0.54\"\n" +
                    "  },\n" +
                    "  {\n" +
                    "    \"lat\": \"-16.4244317845\",\n" +
                    "    \"lon\": \"-71.52562186\",\n" +
                    "    \"type\": \"1\",\n" +
                    "    \"distance\": \"1.87\"\n" +
                    "  },\n" +
                    "  {\n" +
                    "    \"lat\": \"-16.4244317845\",\n" +
                    "    \"lon\": \"-71.52562186\",\n" +
                    "    \"type\": \"1\",\n" +
                    "    \"distance\": \"0.22\"\n" +
                    "  }\n" +
                    "  {\n" +
                    "    \"lat\": \"-16.4244317845\",\n" +
                    "    \"lon\": \"-71.52562186\",\n" +
                    "    \"type\": \"1\",\n" +
                    "    \"distance\": \"2.69\"\n" +
                    "  }\n" +
                    "]";
            JSONArray objectsArray = (JSONArray) new JSONParser().parse(objects);

            objectsArray.stream().sorted(Comparator.comparing(a -> ((JSONObject) a).get("distance")));

我收到以下错误。

Error:(42, 62) java: incompatible types: inferred type does not conform to upper bound(s)
        inferred: java.lang.Object
        upper bound(s): java.lang.Comparable<? super java.lang.Object>

我还提到了this 问题。但我觉得这可以通过流更简单的方式完成。有任何想法吗?我对 JSONObject 使用以下依赖项

    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
    </dependency>

【问题讨论】:

  • 您使用的是哪个JSONArray 类?例如,我发现 javax.json.JSONArray 扩展了 List&lt;JsonValue&gt;,而不是 List&lt;JsonObject&gt;,这是您的代码所期望的。

标签: java json java-stream


【解决方案1】:

您可能正在寻找这样的代码:

objectsArray.stream().sorted(
    Comparator.comparing(a ->  Double.valueOf((String)((JSONObject) a).get("distance")))
).forEach(o -> System.out.println(o));

我们使用的演员表如下:

((JSONObject) a).get("distance")) //to get the distance as an Object

然后

((String) ((JSONObject) a).get("distance"))) // this Object is actually a String, so cast to it

然后

Double.valueOf((String)((JSONObject) a).get("distance")) //this String, however, is a double, and we want to compare the double size, not alphabetically 

因为您需要根据距离的双精度值进行比较。

但是,还有很多方面需要改进。由于我们在这里使用 OOP,因此至少将“字符串”流转换为一些有意义的对象可能是有意义的。

编辑:

您可能应该这样做:

//define a class to conform with OOP stuff
public static class Coordinate {

    private final Double lat;
    private final Double lon;
    private final Integer type;
    private final Double distance;

    public Coordinate(Double lat, Double lon, Integer type, Double distance){
        this.lat = lat;
        this.lon = lon;
        this.type = type;
        this.distance = distance;
    }

    public Double getDistance() {
        return distance;
    }
}

// define a conversion logic
private static Coordinate convert(JSONObject raw){
    Double distance = Double.valueOf((String) raw.get("distance"));
    Double lon = Double.valueOf((String) raw.get("lon"));
    Double lat = Double.valueOf((String) raw.get("lat"));
    Integer type = Integer.valueOf((String) raw.get("type"));
    return new Coordinate(lat, lon, type, distance);
}

那么你的方法就像写一样简单:

List<JSONObject> coordinates = (List<JSONObject>)new JSONParser().parse(objects);
List<Coordinate> sortedCoordinates = coordinates
                .stream()
                .map(raw -> convert(raw))
                .sorted(Comparator.comparing(Coordinate::getDistance))
                .collect(Collectors.toList());

我给您的另一个提示是使用更好的库,例如 https://github.com/FasterXML/jackson 进行对象映射。

【讨论】:

  • .map(raw -&gt; convert(raw)) 甚至可以替换为.map(ClassWithConvertMethod::convert)
  • @Lino 是的,我不想输入我的 className,因为我不确定它是否不会混淆 OP。
【解决方案2】:

试试这个。

JSONArray objectsArray = (JSONArray) new JSONParser().parse(OBJECTS);
List<JSONObject> jo = (List<JSONObject>) objectsArray.parallelStream()
                .sorted(Comparator.comparing((t) -> Double.parseDouble(((JSONObject) t).get("distance").toString())))
                .collect(Collectors.toList());

System.out.println(JSONArray.toJSONString(jo));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多