java - 基于 2 个对象对列表中的元素进行分组,如果它们具有相同的值,则仅显示该元素一次,并显示计数

标签 java list collections java-stream grouping

我有一段代码如下:

List<Locations> locationList = getLocations(locations, eventTypeList, eventIdentityData);

这给了我一个位置列表。

我的Location.java类如下:

private String city;
private String country;
private double latitude;
private double longitude;

它们也有 getter 和 setter。

因此,如果我得到如下输出:

"locations": [
    {
        "city": "Dubai",
        "country": "United Arab Emirates",
        "latitude": 25.2048493,
        "longitude": 55.2707828
    },
    {
        "city": "Dubai",
        "country": "United Arab Emirates",
        "latitude": 25.2048493,
        "longitude": 55.2707828
    },
    {
        "city": "Delhi",
        "country": "India",
        "latitude": 10.2048493,
        "longitude": 40.2707828
    }
]

在上面的响应中,有 2 个元素具有相同的纬度和经度值,因此这些元素应该组合在一起,并应显示为一个元素,计数为 2。输出应如下所示:

"locations": [
    {
        "city": "Dubai",
        "country": "United Arab Emirates",
        "latitude": 25.2048493,
        "longitude": 55.2707828,
        "count": 2
    },
    {
        "city": "Delhi",
        "country": "India",
        "latitude": 10.2048493,
        "longitude": 40.2707828,
        "count": 1
    }
]

我知道我需要做的一件事是在 Location 类中声明 count 变量。另外,这意味着我需要根据纬度和经度值进行分组(对于要分组在一起的元素来说,这两个值必须相同)。有人可以帮我根据我需要的输出修改此列表吗?

最佳答案

使用流按位置组合纬度和经度的唯一表示对位置进行分组。然后将计数设置为等于每个组的大小。

private static Collection<Location> count(Collection<Location> input) {
    return input.stream()
                .collect(groupingBy(locaction -> BigDecimal.valueOf(locaction.getLatitude()).setScale(7, ROUND_DOWN).toPlainString() +
                                                 BigDecimal.valueOf(locaction.getLongitude()).setScale(7, ROUND_DOWN).toPlainString()))
                .values().stream()
                .map(locations -> locations.get(0).setCount(locations.size()))
                .collect(toList());
}

示例:

public class Main {

    public static void main(String[] args) {
        Location location1 = new Location("a", "b", 1.23232321, 4.56);
        Location location2 = new Location("c", "d", 1.23232328, 4.56);
        Location location3 = new Location("e", "f", 7.89, 0.12);
        Collection<Location> count = count(Arrays.asList(location1, location2, location3));
        System.out.println(count);
    }

    private static Collection<Location> count(Collection<Location> input) {
        return input.stream()
                    .collect(groupingBy(locaction -> BigDecimal.valueOf(locaction.getLatitude()).setScale(7, ROUND_DOWN).toPlainString() +
                                                     BigDecimal.valueOf(locaction.getLongitude()).setScale(7, ROUND_DOWN).toPlainString()))
                    .values().stream()
                    .map(locations -> locations.get(0).setCount(locations.size()))
                    .collect(toList());
    }

    public static class Location implements Serializable {
        private String city;
        private String country;
        private double latitude;
        private double longitude;
        private int count;

        public Location(String city, String country, double latitude, double longitude) {
            this.city = city;
            this.country = country;
            this.latitude = latitude;
            this.longitude = longitude;
        }

        public double getLatitude() {
            return latitude;
        }

        public double getLongitude() {
            return longitude;
        }

        public Location setCount(int count) {
            this.count = count;
            return this;
        }
    }
}

关于java - 基于 2 个对象对列表中的元素进行分组,如果它们具有相同的值,则仅显示该元素一次,并显示计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57806962/

相关文章:

java - 比较日期与 JUnit 测试

python - 如何使用列表替换字符串的某些部分?

java - 将对象列表连接到 JTable

Java vector 帮助

java - LibGdx 中的内存使用

Java : Accessor methods vs protected fields

c# - 根据条件合并 List<T> 中的两个或多个 T

java - Java 中的日期排序

java - 如何在 Java Canvas 中绘制 JSON 文本?

Java CodingBat 数组列表