使用将 Comparator 作为参数实现的 class 的问题

Problems using a class that implements Comparator as a parameter

我有一张地图需要根据非常具体的条件进行排序,所以我创建了以下 class:

private class EventComparator implements Comparator<Map.Entry<Event, gohs.scyoly.core.Entry>> {

    Crew crew;

    public EventComparator(Crew crew) {
        this.crew = crew;
    }

    @Override
    public int compare(java.util.Map.Entry<Event, Entry> o1,
            java.util.Map.Entry<Event, Entry> o2) {

        // algorithm for comparing
    }

}

然后我创建了一个单独的静态 class 和将使用冒泡排序的函数:

public static <K, V> void mapSort(LinkedHashMap<K, V> map,
            Comparator<Map.Entry<? super K, ? super V>> comparator) {

        // array list is more efficient
        ArrayList<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
        int i; // var for iterating
        boolean swap = true; // false if no swaps occurred (list is sorted)
        Map.Entry<K, V> temp;

        while(swap) {
            swap = false; // assume no swap will occur
            for (i = 0; i < entries.size() -1; i++)
                if (comparator.compare(entries.get(i), entries.get(i + 1)) > 0) {
                    temp = entries.get(i);
                    entries.set(i, entries.get(i + 1));
                    entries.set(i + 1, temp);
                    swap = true;
                }
        }

        // re-factor the original map
        map.clear();
        for (Map.Entry<K, V> entry : entries)
            map.put(entry.getKey(), entry.getValue());
    }

需要注意的重要一点是函数采用的参数。我以为我可以简单地执行以下操作: mapSort(sorted, new EventComparator(crew)) 但 Eclipse 警告我第二个参数的类型不正确。关于如何实现这一点有什么建议吗?

应 Tim 的要求,这是调用它的代码:

    // Reduce team size if necessary
    if (crew.getSize() > 15) {
        System.out.println("Crew reduction neccessary"); // DEBUG

        // get list of the next step down in feeder
        LinkedHashMap<Event, gohs.scyoly.core.Entry> sorted = new LinkedHashMap<>(feeder.size());

        for (Map.Entry<Event, Stack<Entry>> feederEntry : feeder.entrySet()) {
            sorted.put(feederEntry.getKey(), feederEntry.getValue().peek());
        }

        BubbleSort.mapSort(sorted, new EventComparator(crew));

        System.out.println(sorted.entrySet()); // DEBUG
    }

对于上下文,该应用程序旨在扫描团队分数以查找事件,这些分数存储为条目,然后输出完美的 "crew",这是一起参加事件的团队的集合。

更新: 我将代码更改为以下内容:

BubbleSort.mapSort(sorted, (Comparator<Map.Entry<Event, gohs.scyoly.core.Entry>>) new EventComparator(crew));

但它仍然给我一个错误消息:

The method mapSort(LinkedHashMap<K,V>, Comparator<Map.Entry<? super K,? super V>>) in the type Assembler.BubbleSort is not applicable for the arguments (LinkedHashMap<Event,Entry>, Comparator<Map.Entry<Event,Entry>>)

[从我的评论中复制]

对于 sortMap 的签名,将 Comparator<Map.Entry<? super K, ? super V>> 更改为 Comparator<Map.Entry<K, V>>。只是开始,我总是难以全神贯注(super vs extends)。

[更新]

Effective Java,第 2 版:"Item 28: Use bounded wildcards to increase API flexibility" 中有一个关于 <? super XXX><? extends XXX> 的很好的部分,特别是他们谈论 'PECS' 的地方 -生产者扩展,消费者超级。

我仍然需要更好地研究这种情况下的原因,但至少我们有了一个起点。

Comparator<Map.Entry<Event,Entry>>不是Comparator<Map.Entry<? super K, ? super V>>的子类型,因为Comparator的类型参数不同。就像 List<String> 不是 List<Object> 的子类型一样,因为 StringObject 是不同的,即使 StringObject 的子类型.

如果要对 Map.Entry 的参数使用通配符,则还需要在 Comparator 的参数级别使用通配符,如下所示:

Comparator<? extends Map.Entry<? super K, ? super V>>