Could somebody show me a quick example how to sort an ArrayList alphabetically in Java 8 using the new lambda syntax.
12 Answers
For strings this would work
arrayList.sort((p1, p2) -> p1.compareTo(p2));
3 Comments
arrayList.sort(Comparator.naturalOrder()).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)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
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
Comparator is entirely unneeded.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
Strings in lexicographic order, it's the default behavior.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
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
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
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
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.