正确排序集合中的相等项目

Properly sort equal items in Collection

根据Documentation Java SE7

This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.

 Collections.sort(gpsDtoList, new Comparator<T>() {

                public int compare(T o1, T o2) {

                    return -o1.getEreigniszeit().compareTo(o2.getEreigniszeit());

                }
            });

知道这个事实,我怎么能用符号表示这些项目确实相等,即使列表中有一个 "higher"(隐含的意思是更年轻 timestamp

测试数据

假设o2.Ereigniszeit = 0000o2.Ereigniszeit = 0000(这只是一个非常简单和抽象的例子)

症结所在

我稍后会处理这些数据并使用此逻辑在 Leaflet 地图上突出显示最新的 (green) 和最旧的 (red) 对象

if (i == 0) {
   properties.put("markerStyle", LATEST);
   } else if (i == gpsDtoList.size() - 1) {
        properties.put("markerStyle", OLDEST);
   }

然而字面意思是equal,我该如何正确处理呢? (我正在处理很多 gps 位置,所以任何 O(N^2) 都是不可接受的。)

返回对象为GpsDTO

public class GpsDTO implements Serializable {
    ....
    public Date getEreigniszeit() {
        return ereigniszeit;
    }

    public void setEreigniszeit(Date ereigniszeit) {
        this.ereigniszeit = ereigniszeit;
    }

我建议你使用NavigableMap;这些按键排序。

// entries will be sorted by your comparator
NavigableMap<Date, List<GpsDTO>> map = new TreeMap<yourComparator>();
// if there is a list already, it will be used; otherwise, a new one will be created
gpsDtoList.forEach(dto -> 
    map.computeIfAbsent(dto.getEreigniszeit(), new ArrayList<>())
                            .add(dto));

// iterate the relevant lists to set the respective markers
map.firstEntry().forEach(dto -> dto.setOldest());
if (map.size() > 1) {
    map.lastEntry().forEach(dto -> dto.setNeweset());
}

这里没有 lambda 表达式:

NavigableMap<Date, List<GpsDTO>> map = new TreeMap<yourComparator>();
for (GpsDTO dto : gpsDtoList) {
    List<GpsDTO> list = map.computeIfAbsent(dto.getEreigniszeit());
    list.add(dto);
}

for (GpsDTO firstDto : map.firstEntry()) {
    setOldestProperty(firstDto);
}
if (map.size() > 1) {
    for (GpsDTO lastDto : map.lastEntry()) {
        setNewestProperty(lastDto);
    }
}

解决方案

首先我确定最新和最旧的日期。

Date youngestDate = null;
Date oldestDate = null;

Collections.sort(gpsDtoList, new Comparator<T>() {

            public int compare(T o1, T o2) {

                return -o1.getEreigniszeit().compareTo(o2.getEreigniszeit());

            }
        });

if (gpsDtoList != null && gpsDtoList.size() > 1) {
            youngestDate = gpsDtoList.get(0).getEreigniszeit();
            oldestDate = gpsDtoList.get(gpsDtoList.size() - 1).getEreigniszeit();
        }

和实际设置逻辑

if (youngestDate != null && oldestDate != null) {
                if (i == 0 || youngestDate.equals(gpsDtoList.get(i).getEreigniszeit())) {
                    properties.put("markerStyle", LATEST);
                } else if (oldestDate.equals(gpsDtoList.get(i).getEreigniszeit())) {
                    properties.put("markerStyle", OLDEST);
                }

            }

测试用例/解释

#1 o1,o2 等于?

youngestDateoldestDate 将被设置,但它们是相同的。

现在,如果 i=0 或等于 youngestDate 它确实是 latest 并获得 属性 else if equals oldestDate 它确实是最旧的。

因此我们成功地将两个 GpsDto 对象设置为 latest,因为它永远不会 运行 else if 语句。

#2 没有数据?

我们做了一些空检查,如果没有数据,我们不会设置特殊属性。

#3 List?

中只有一个 GpsDto 对象

我们不需要在这里设置任何特殊属性,我的定义是"stateless"我们不知道它是第一个还是最后一个。 (偷懒我)

如果我没有完全错的话我在 O(n)