Using Comparable to compare generic variables

懵懂的女人 提交于 2021-02-08 04:37:27

问题


For one of the Homeworks in my class, we have a collection of a class titled Pair and we need to sort it in ascending order based on the value of the key.

I could apply this if the keys were strings or integers, but how do I write code that would compare my items when they're Generic as seen below?

The professor in my class explained what to do for integers or strings but when my variables are generic I'm at a complete loss.

Below are copies of the relevant parts of my code.

import java.util.*;


public class Utils {

    public static<K extends Comparable<K>, V> Collection<Pair<K,V>> sortPairCollection(Collection <Pair<K,V>> col){
        ArrayList <Pair<K,V>> list = new ArrayList<>();
        //Code to compare

        return list;
    }

    public static void main(String[] args) {
        ArrayList <Pair<String,Integer>> list = new ArrayList<>();
        Pair<String, Integer> e = new Pair<>("One", 1);
        list.add(e);
        Pair<String, Integer> f = new Pair<>("Two", 2);
        list.add(f);

        Utils help = new Utils();
        help.sortPairCollection(list);
    }
}

This second part here is the code for my Pair class. import java.io.Serializable; import java.util.Objects;

public class Pair <K,V> extends Object implements Serializable, Cloneable{


    public Pair(K k, V v){
       this.k = k;
       this.v = v;
    }


    public K k(){
       return k;
    }


    public V v(){
       return v;
    }


   /*
   ... //irrelevant data omitted
   */

   private final K k;
   private final V v;
}

回答1:


Option 1.Use a Comparator

public class Cmp<K extends Comparable<K>, V> implements Comparator<Pair<K, V>> {
   @Override
   public int compare(Pair<K, V> o1, Pair<K, V> o2) {
      return o1.k.compareTo(o2.k);
   }
}

public class Utils {
    public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(
            Collection<Pair<K, V>> col) {
        ArrayList<Pair<K, V>> list = new ArrayList<>();
        Collections.sort(list, new Cmp<>());
        return list;
    }
}

Option 2. Implement Comparable

public class Pair<K extends Comparable<K>, V> implements Comparable<Pair<K, V>> {
    private K k;
    private V v;
    @Override
    public int compareTo(Pair<K, V> o) {
        return k.compareTo(o.k);
    }
}
public class Utils {
    public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(Collection<Pair<K, V>> col) {
        ArrayList<Pair<K, V>> list = new ArrayList<>();
        Collections.sort(list);
        return list;
    }
}

Or just

public class Utils {
    public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(Collection<Pair<K, V>> col) {
        ArrayList<Pair<K, V>> list = new ArrayList<>();
        Collections.sort(list, (p, o) -> p.k.compareTo(o.k));
        return list;
    }
}

You don't have do create an instance for your static method btw. just invoke

Utils.sortPairCollection(list);



回答2:


import java.util.*;
public class Utils {

public static <K extends Comparable<K>, V> Collection<Pair<K, V>> sortPairCollection(Collection<Pair<K, V>> col) {
    ArrayList<Pair<K, V>> list = new ArrayList<>(col);
    //Code to compare
    list.sort(Comparator.comparing(Pair::k)); //this is the only change needed
    return list;
}

public static void main(String[] args) {
    List<Pair<String, Integer>> listas = Arrays.asList(
        new Pair<>("One", 1),
        new Pair<>("Two", 2));
    System.out.println(Utils.sortPairCollection(listas));

}

What we did here is that we extracted an already Camparable key from our Pair and passed that to the Comparator class static method which will generate a custom Comparator for our Pair class. See the Javadoc for Comaparator here




回答3:


If you are a clean and elegant code lover like me then you can use the power of lambda expression to create an anonymous function (function with no name) on the spot that handles the comparison logic. Technically it is the same as when using Comparable or Comparator functional interfaces but using lambdas you don't have to write boilerplate code by creating classes just for one function. Instead you create that function on spot int the form of lambda expression, java handles the rest. Lambda expressions were introduced in Java 8.

Lambda expression have the form ( <parameters> ) -> { //body of the function }

public class Pair<K ,V extends Comparable<V>> {
private K k;
private V v;
public Pair(K k, V v){
   this.k = k;
   this.v = v;
}
public K k(){
   return k;
}
public V v(){
   return v;
}
}


public static void main(String[] args) {

        ArrayList <Pair<String,Integer>> list = new ArrayList<>();
        Pair<String, Integer> e = new Pair<>("One", 1);
        list.add(e);
        Pair<String, Integer> f = new Pair<>("Two", 2);
        list.add(f);

        // Second argument to this sort function is a lambda expression
        Collections.sort( list , (pair1 , pair2)->{

            return pair1.v().compareTo(pair2.v());

        });
    }
}

The data type of pair1 and pair2 will be Pair Here are some starter links about lambda expression and functional interfaces

Functional Interfaces: https://www.geeksforgeeks.org/functional-interfaces-java/

Lambda Expressions: https://www.geeksforgeeks.org/lambda-expressions-java-8/



来源:https://stackoverflow.com/questions/53202231/using-comparable-to-compare-generic-variables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!