简体   繁体   中英

How to sort a Collection of generic Pairs

This is homework, so I would prefer some explanation rather than just giving me the answer.

I have a generic Pair class that can take any key value K, and any value V.

The goal is to write a generic method:

public static <...> Collection<Pair<...>> sortPairCollection(Collection <Pair<....>> col)

The only other guideline is that the K type must implement Comparable<...>.

After some digging, I saw people recommend something like this:

public static Collection<Pair<?,?>> sortPairCollection(Collection<Pair<?,?>> col)
{
    Collections.sort(col, new Comparator<Pair<?,?>>(){
        @Override
        public int compare(Pair<?, ?> x, Pair<?, ?> y) {
            return (Integer)x.v() - (Integer)y.v();
        }
    });
}

But that doesn't work for me, I get an error that says the sort method is not applicable to those parameters. I don't really know where to go from here.

Collections.sort only works on List instances, not on general Collections . It does not make sense to sort a HashSet for example.

Secondly, due to arithmetic overflow, you should avoid using subtraction in a comparator like that. It is always better to use Integer.compare .

Also, a method with return type Collection<Pair<?,?>> must return something. You could return col , but as you are mutating col it makes more sense to make the method void .

Another point is that it looks like your method will throw a ClassCastException unless the second type parameter is Integer (I am assuming v() has return type V ). If this is the case, there is no point writing your method for Pair<?, ?> as you could just use Pair<?, Integer> .

Finally, due to the way generics work in Java, you won't actually be able to pass in a List<Pair<String, Integer>> with your current signature, because a List<Pair<String, Integer>> is not a List<Pair<?, Integer>> (see this question or this one ). If you want to be able to do that, the argument should have type List<? extends Pair<?, Integer>> List<? extends Pair<?, Integer>> .

Edit

I now realise that I haven't really answered the question. The idea is not to mutate the original collection, but return a new one. Also the sorting should be done by key, not value, because K must implement Comparable .

In order to use the compareTo method, you need to indicate that K extends Comparable . The way to do this is to use the signature

public static <K extends Comparable<? super K>, V> Collection<Pair<K, V>> sortPairCollection(Collection<Pair<K, V>> col)

This is a bit of a mouthful - generics have significantly increased the complexity of method signatures.

K extends Comparable<? super K> K extends Comparable<? super K> says that K s can be compared with other K s.

You will still need to use a List though. You could use the ArrayList constructor that accepts a Collection .

As requested, I'll leave it up to you to write the correct code.

Here is the complete program:

public static <K extends Comparable<? super K>, V extends Comparable<? super V>> void sortPairCollection(List<Pair<K, V>> col){

        Collections.sort(col, new Comparator<Pair<K,V>>(){

            public int compare(Pair<K, V> o1, Pair<K, V> o2) {

                int keyflag = o1.getValue().compareTo(o2.getValue()) == 0 ? o1.getKey().compareTo(o2.getKey()): o1.getValue().compareTo(o2.getValue()) ;

                return keyflag;

            }});

    }

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