使用 java 8 流 api 对 json 数组进行排序

Pra*_*rma 2 java json java-stream

我一直在尝试使用 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")));
Run Code Online (Sandbox Code Playgroud)

我收到以下错误。

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>
Run Code Online (Sandbox Code Playgroud)

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

    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

Nik*_*hev 5

也许您正在寻找这样的代码:

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

我们使用的强制转换如下:

((JSONObject) a).get("distance")) //to get the distance as an Object
Run Code Online (Sandbox Code Playgroud)

进而

((String) ((JSONObject) a).get("distance"))) // this Object is actually a String, so cast to it
Run Code Online (Sandbox Code Playgroud)

进而

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

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

然而,还有很多事情需要改进。由于我们在这里使用 OOP,因此至少将“String”流转换为一些有意义的对象可能是有意义的。

编辑:

您可能应该这样做:

//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);
}
Run Code Online (Sandbox Code Playgroud)

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

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());
Run Code Online (Sandbox Code Playgroud)

我为您提供的另一个建议是使用更好的库(例如https://github.com/FasterXML/jackson)来进行对象映射。