3

I am trying to sort list of string through my own comparator. I saw the below template for list of developers.

//lambda
listDevs.sort((Developer o1, Developer o2)->o1.getAge()-o2.getAge());

My code: (this is giving me compile error)

List<String> s = new ArrayList<>();  
Collections.sort(s, (String a, String b)-> {
    return a.length() > b.length()
});

This code is not compiling. Can someone help me what is wrong with what I am doing?

3
  • 1
    You should better use Comparator.comparingInt(String::length) Commented Jul 22, 2019 at 10:30
  • Issue was I was returning boolean, return type is int. Commented Sep 21, 2019 at 16:38
  • Sure, but that doesn’t change the fact that s.sort(Comparator.comparingInt(String::length)); is preferable, just like the original example should have been listDevs.sort(Comparator.comparingInt(Developer::getAge)); Using minus for comparators is a bad habit. It works here, as the values are never negative, but when sticking to the pattern for all numerical comparators, you will write broken comparators some day, as the difference between two int values can be larger than the value range of int, leading to overflows. You can use Integer.compare(x, y) instead or just use comparingInt Commented Sep 23, 2019 at 7:48

2 Answers 2

3

Arrays.sort is used for sorting Arrays not for Collection objects, use Collections.sort to sort ArrayList

Collections.sort(s,(a,b)->a.length()-b.length());

And corresponding lambda expression is wrong (String a,String b)-> a.length() > b.length() which returns Boolean value. Where Comparator.compare should return int value. And also the type of the parameters can be explicitly declared or it can be inferred from the context.

int compare(T o1, T o2)

You can also use List.sort

s.sort((a,b)->a.length()-b.length());
Sign up to request clarification or add additional context in comments.

Comments

2

There are 2 unrelated problems with your code:

[1] There are two ways to write lambdas.

You can either write a single expression serving as the return value:

s.sort((a, b) -> a.length() - b.length());

Or you can involve a code block; but if you do that, return (and semicolons) have to show up:

s.sort((a, b) -> {
    return a.length() - b.length();
});

Generally if you can make it work with a single expression, just do that; it's shorter. In your example you're using braces (so, the second form), but you don't have the return keyword nor the required semicolon.

Also, the types of the lambda arguments are optional. Generally if from context it is clear, just omit these: (a, b) -> a.length() - b.length()

[2] a comparator should return 0 if the arguments are equal, a negative number (any negative number, it doesn't matter which one) if a is 'smaller' than b, and a positive number if a is 'larger' than b. You are returning a boolean (you are using a greater than sign; the result of that expression is 'true' or 'false'; you need a number instead.

The solution seems trivial here: use minus instead.

[3] a bonus tip: There are utility methods for comparing based on field: Comparator.comparingInt(String::length) will do what you want in a way that is easier to read and less error prone. Also, instead of Collections.sort(list, comparator) you can just write list.sort(comparator); easier on the eyes, shorter, and more idiomatic.

Let's put it all together:

List<String> s = new ArrayList<>();  
s.sort(Comparator.comparingInt(String::length));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.