简体   繁体   中英

Problems using a class that implements Comparator as a parameter

I have a map that needs to be sorted with very specific conditions, so I created the following 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
    }

}

I then created a separate static class and function that would use bubble sort:

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

The important thing to note is the parameters that the function takes. I thought that i could simply do the following: mapSort(sorted, new EventComparator(crew)) but Eclipse warns me that the second parameter is not of the correct type. Any suggestions on how to achieve this?

As requested by Tim, here is the code that calls it:

    // 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
    }

For context, the application aims to scan in team scores for events, which get stored as entries, and then output the perfect "crew", which is a collection of teams that compete in the events together.

Update: I changed the code to the following:

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

But it still gives me an error with the following message:

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

[Copied from my comment]

For the signature for sortMap, change Comparator<Map.Entry<? super K, ? super V>> Comparator<Map.Entry<? super K, ? super V>> Comparator<Map.Entry<? super K, ? super V>> to Comparator<Map.Entry<K, V>> . Just to get started, I always have trouble to wrap my mind around it ( super vs extends ).

[Update]

There is a nice section about <? super XXX> <? super XXX> and <? extends XXX> <? extends XXX> in Effective Java, 2nd Edition: "Item 28: Use bounded wildcards to increase API flexibility", particularly where they talk about 'PECS' - Producer-Extends, Consumer-Super.

I still would need to research better as to the why's in this case, but at least we have a starting point.

Comparator<Map.Entry<Event,Entry>> is not a subtype of Comparator<Map.Entry<? super K, ? super V>> Comparator<Map.Entry<? super K, ? super V>> Comparator<Map.Entry<? super K, ? super V>> , because the type parameter of Comparator is different. It's just like how List<String> is not a subtype of List<Object> because String and Object are different, even though String is a subtype of Object .

If you want to use wildcards for the parameters of Map.Entry , you will also need a wildcard at the level of the parameter of Comparator , like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM