54

Could somebody show me a quick example how to sort an ArrayList alphabetically in Java 8 using the new lambda syntax.

1

12 Answers 12

75

For strings this would work

arrayList.sort((p1, p2) -> p1.compareTo(p2));
Sign up to request clarification or add additional context in comments.

3 Comments

Better: arrayList.sort(String::compareTo)
Note that both .sort(String::compareTo) and .sort(Comparator.naturalOrder()) will sort all upper case letters before any lower case letters. Usually what you want is .sort(String::compareToIgnoreCase)
33

Are you just sorting Strings? If so, you don't need lambdas; there's no point. You just do

import static java.util.Comparator.*;

list.sort(naturalOrder());

...though if you're sorting objects with a String field, then it makes somewhat more sense:

list.sort(comparing(Foo::getString));

Comments

9

Use list.sort(String::compareToIgnoreCase)

Using list.sort(String::compareTo) or list.sort(Comparator.naturalOrder()) will give incorrect (ie. non-alphabetical) results. It will sort any upper case letter before all lower case letters, so the array ["aAAA","Zzz", "zzz"] gets sorted to ["Zzz", "aAAA", "zzz"]

Comments

8

Suppose you have List of names(String) which you want to sort alphabetically.

List<String> result = names.stream().sorted(
                 Comparator.comparing(n->n.toString())).collect(Collectors.toList());

its working perfectly.

1 Comment

The Comparator is entirely unneeded.
4

In functional programming, you're not using the old objects to operate on them, but creating the new one in such a fashion:

list.stream().sorted().map(blah-blah).filter(...)...

7 Comments

This is incorrect, as now the stream no longer consists of the old elements, but of the mapped and filtered version. Consider a bank account which you want to sort by person name: If you do it like you suggest, then you start of with a stream of bank accounts, and end up with a stream of person names, while you want to end up with a stream of bank accounts again.
Generally, when you write your programs in FP-style, you don't need to iterately save the results. So, this all is a new list(s): list.stream().sorted() is not sorting the old list, but creating the new one.
And that list has just became useless as you only have the person's name left (in my example), and you cannot reference it back (directly) to their bank account anymore.
Also, possibly a source of your confusion (nothing to blame), is that the OP requested a method to sort a list, yet you only return an intermediary stream, you also will need to store it at some point, which you omitted from your answer. By trying to implement that, you may see the issue yourself aswell.
@skiwi there's no need to specify the sort operator as OP wanted to sort Strings in lexicographic order, it's the default behavior.
|
3

Lambdas shouldn't be the goal. In your case, you can sort it the same way as in Java 1.2:

Collections.sort(list); // case sensitive
Collections.sort(list, String.CASE_INSENSITIVE_ORDER); // case insensitive

If you want to do it in Java 8 way:

list.sort(Comparator.naturalOrder()); // case sensitive
list.sort(String.CASE_INSENSITIVE_ORDER); // case insensitive

You can also use list.sort(null) but I don't recommend this because it's not type-safe.

Comments

2

A really generic solution would be to introduce some StreamUtil like

public class StreamUtil {

    private StreamUtil() {
    }       

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static <TYPE> Comparator<TYPE> sort(Function<TYPE, ? extends Comparable> getterFunction, boolean descending) {
        if (descending) {
            return (o1, o2) -> getterFunction.apply(o2).compareTo(getterFunction.apply(o1));
        }
        return (o1, o2) -> getterFunction.apply(o1).compareTo(getterFunction.apply(o2));
    }

}

The call would look something like

list.stream().sorted(sort(YourClass::getSortProperty, true));

Comments

2

Most concise:

Collections.sort(stringList, String::compareToIgnoreCase);

Comments

2

If you have an array with elements that have natural ordering (i.e String, int, double); then it can be achieved by:

List<String> myList = new ArrayList<>();
myList.add("A");
myList.add("D");
myList.add("C");
myList.add("B");
myList.sort(Comparator.comparing(s -> s));
myList.forEach(System.out::println);

If on the another hand you have an array of objects and you want to sort base on some sort of object field, then you can use:

class User {
    double score;
    // Constructor // Getters // Setters
}

List<User> users = new ArrayList<>();
users.add(new User(19d));
users.add(new User(67d));
users.add(new User(50d));
users.add(new User(91d));

List<User> sortedUsers = users
        .stream()
        .sorted(Comparator.comparing(User::getScore))
        .collect(Collectors.toList());

sortedUsers.forEach(System.out::println);

If the sorting is more complex, then you would have to write your own comparator and pass that in.

Comments

1
 List<Product> list = new ArrayList<>();
        List<String> list1 = new ArrayList<>();
        list.add(new Product(1));
        list.add(new Product(2));
        list.add(new Product(3));
        list.add(new Product(10));
 Collections.sort(list, Comparator.comparing((Product p) -> p.id));
        for (Product p : list) {
            System.out.println(p.id);
        }

1 Comment

Sticking to functional programming, for (Product p : list) { System.out.println(p.id); } can be written as list.stream().forEach(System.out::println);
0

The syntax including a custom comparator is quite simple, and quick, for example here the ArrayList being sorted contains JSONObjects, and I will sort it based on a property called 'order':

arrayList.sort((JSONObject o1, JSONObject o2)->o1.getInt("order")-o2.getInt("order"));

I think this is a really nice and concise syntax, easy to read and less bulky than non-lambda syntax.

Comments

0

To sort ArrayList of String in n descending order just refer to this type And if You are looking for ascending then replace a1 with a2.

Collections.sort(ArrayListName,(a1,a2)->a2.compareTo(a1));

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.