Having an error when using String in Comparator

ball_jan :

I am trying to create a class implementing comparable. When all the class elements are integer, everything works well. When I go with String and use comparing rather than comparingInt, I receive the following errors.

  • Incorrect number of type arguments for generic method comparing(Function) of type Comparator; it cannot be parameterized with arguments

  • The type myClassdoes not define getFrom(T) that is applicable here

public class myClass implements Comparable<myClass> {
    @Column (name="From")
    private String from;
    @Column (name="To")
    private String to;
    @Column (name="With")
    private String with;
    @Column (name="amount")
    private int amount;

    // Setters, getters, constructor

    Comparator<myClass > comp = Comparator.<myClass>comparing(myClass::getFrom)
            .thenComparing(myClass::getTo)
            .thenComparing(myClass::getWith)
            .thenComparingInt(myClass::getAmount);
    @Override
    public int compareTo(myClass o) {
        return comp.compare(this, o);
    }
}

Could someone point out what I might be missing here?

michalk :

Comparator::comparing is a generic method that takes a function that is used to extract the value to be compared. You passed a method reference to myClass::getFrom method which returns a String and will be invoked on myClass type object (through Function::apply). That is why you have to pass generic types myClass and String.

However you could ommit those generic types because you are assigning your comparator to Comparator<myClass> comp variable so types can be inferred automatically (also using types from your method reference used).

Looking further let's look at Comparator::comparing(Function) method implementation :

static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> var0) {
    Objects.requireNonNull(var0);
    return (Comparator)((Serializable)((var1x, var2x) -> {
        return ((Comparable)var0.apply(var1x)).compareTo(var0.apply(var2x));
    }));
}

Here T will be myClass and U will be String. Function var0 will take myClass as parameter and will return String (so method reference to myClass::getFrom will work here - generally it will be like invoking getFrom on myClass object). Actually as you can see this method will return a Comparator as a lambda function which will use function var0 to extract values from var1x and var2x (both of them will be myClass types). For me it looks a bit like a closure.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=127788&siteId=1