The problem is, that Java can not deduce the generic types for some complex expressions. The first statement works, whereas the second statement leads to a compile-time error:
Comparator<String> comparator = Comparator.comparing(String::toLowerCase);
Comparator<String> comparator = Comparator.comparing(String::toLowerCase).reversed();
There are several ways to solve the problem. Here are three of them:
Store the intermediate Comparator in a variable:
Comparator<String> comparator = Comparator.comparing(String::toLowerCase);
System.out.println(
Arrays.stream(stringsArray)
.sorted(comparator.reversed())
.collect(Collectors.toList()));
Use String.CASE_INSENSITIVE_ORDER:
System.out.println(
Arrays.stream(stringsArray)
.sorted(String.CASE_INSENSITIVE_ORDER.reversed())
.collect(Collectors.toList()));
Add explicit type parameters:
System.out.println(
Arrays.stream(stringsArray)
.sorted(Comparator.<String,String>comparing(String::toLowerCase).reversed())
.collect(Collectors.toList()));
Answer from nosid on Stack OverflowThe problem is, that Java can not deduce the generic types for some complex expressions. The first statement works, whereas the second statement leads to a compile-time error:
Comparator<String> comparator = Comparator.comparing(String::toLowerCase);
Comparator<String> comparator = Comparator.comparing(String::toLowerCase).reversed();
There are several ways to solve the problem. Here are three of them:
Store the intermediate Comparator in a variable:
Comparator<String> comparator = Comparator.comparing(String::toLowerCase);
System.out.println(
Arrays.stream(stringsArray)
.sorted(comparator.reversed())
.collect(Collectors.toList()));
Use String.CASE_INSENSITIVE_ORDER:
System.out.println(
Arrays.stream(stringsArray)
.sorted(String.CASE_INSENSITIVE_ORDER.reversed())
.collect(Collectors.toList()));
Add explicit type parameters:
System.out.println(
Arrays.stream(stringsArray)
.sorted(Comparator.<String,String>comparing(String::toLowerCase).reversed())
.collect(Collectors.toList()));
I found the solution :
.sorted((String e) -> e.toLowerCase)
I think the problem with the syntax
.sorted(String::toLowerCase)
is that the compiler then expects to pass an Object to the instance method toLowerCase of String. So I need to make my own lambda method, without ignoring the type of the lambda parameter (String), otherwise the compiler still can't resolve it.
Videos
Solution for Java 8 based on java.util.Comparator.comparing(...):
Comparator<String> c = Comparator.comparing(String::toString);
or
Comparator<String> c = Comparator.comparing((String x) -> x);
You may write your own comparator
public class ExampleComparator implements Comparator<String> {
public int compare(String obj1, String obj2) {
if (obj1 == obj2) {
return 0;
}
if (obj1 == null) {
return -1;
}
if (obj2 == null) {
return 1;
}
return obj1.compareTo(obj2);
}
}
(The answer to the question is at the end of this post)
Hey guys,
so here's a quote block on the method from the API:
static <T,U extendsComparable<? super U>>Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)Accepts a function that extracts a
Comparablesort key from a typeT, and returns aComparator<T>that compares by that sort key.The returned comparator is serializable if the specified function is also serializable.
API Note: For example, to obtain a
Comparatorthat comparesPersonobjects by their last name,
Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
To verify what the API said: I created a simple Person class
class Person
{
private String lastName;
public Person(String lastName)
{
this.lastName=lastName;
}
public String getLastName()
{
return lastName;
}
}Then as expected this works:
Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
---------------------------------------
Q1: But this doesn't work: Comparator<Person> byLastName = Comparator.comparing(person->person.getLastName()); Eclipse doesn't even pick up the method getLastTime(), only Object's methods are present.
Q2: Then I also wondered why does the method done up by the API work? As seen by the method signature <T,U extends Comparable<? super U>>, T is input parameter thus refers to Person type and U is the output parameter thus refers to String type.
However, Person is not a subtype of Comparable<? super String>. Hence, the one in the API shouldn't work too.
My guess:My understanding of the Function<? super T,? extends U> keyExtractor is probably wrong.
-------------------------------------
Anyhow, can some kind soul help out?
Edit:Spelling error
Edit 2: Big thanks to u/knoam (sort of a TLDR for the thread)Answer for Q1: Eclipse is buggy i guess, NetBeans works.Answer for Q2: <T,U extends Comparable <? super U> > made me think that both T and U should be subtypes of Comparable. It's only U.