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

时间:2015-05-03 19:56:56

标签: java sorting generics parameters comparator

我有一张需要按照非常具体的条件排序的地图,所以我创建了以下类:

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
    }

}

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

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
    }

对于上下文,该应用程序旨在扫描事件的团队分数,将其存储为条目,然后输出完美的&#34; crew&#34 ;,这是一组在一起竞争事件的团队。

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

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

2 个答案:

答案 0 :(得分:1)

[从我的评论中复制]

对于sortMap的签名,请将Comparator<Map.Entry<? super K, ? super V>>更改为Comparator<Map.Entry<K, V>>。为了开始,我总是很难绕过它(super vs extends)。

[更新]

有效Java中的<? super XXX><? extends XXX>有一个很好的部分,第2版:&#34;项目28:使用有界通配符来增加API灵活性&#34;,特别是在他们谈论的地方&#39; PECS&#39; - Producer-Extends,Consumer-Super。

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

答案 1 :(得分:0)

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

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

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