在Collection中正确排序相同的项目

时间:2018-02-15 13:50:35

标签: java algorithm sorting collections comparator

根据Documentation Java SE7

  

此类保证稳定:由于排序,相同的元素不会被重新排序。

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

                public int compare(T o1, T o2) {

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

                }
            });

知道了这个事实,我怎么能象征这些项目确实是平等的,尽管有一个更高的&#34;在列表中(隐含意味着更年轻timestamp

TESTDATA

让我们说o2.Ereigniszeit = 0000o2.Ereigniszeit = 0000 (这只是一个非常简单和抽象的例子)

The Crux

我稍后处理此数据并使用此逻辑突出显示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;
    }

2 个答案:

答案 0 :(得分:1)

我建议您使用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());
}

没有lambdas,这是相同的:

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

答案 1 :(得分:-1)

解决方案

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

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并获得了财产 否则,如果等于oldestDate,那确实是最老的。

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

#2没有数据?

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

#3只有GpsDto中的一个List对象?

我们不需要在此处设置任何特殊属性,因为我的定义是“无状态”&#34;我们不知道它是第一个还是最后一个。 (懒惰我)

如果我不完全错,我会在O(n)