Zadanie:
Masz listę people
obiektów klasy, Person
która ma pola name
i age
. Twoim zadaniem jest posortowanie tej listy najpierw według name
, a następnie według age
.
Java 7:
Collections.sort(people, new Comparator<Person>() {
public int compare(Person a, Person b) {
return a.getName().compare(b.getName());
}
});
Collections.sort(people, new Comparator<Person>() {
public int compare(Person a, Person b) {
return Integer.valueOf(a.getAge()).compare(b.getAge());
}
});
Scala:
val sortedPeople = people.sortBy(p => (p.name, p.age))
Aktualizacja
Odkąd napisałem tę odpowiedź, nastąpił spory postęp. Lambdy (i odwołania do metod) w końcu wylądowały w Javie i szturmem podbijają świat Javy.
Tak będzie wyglądał powyższy kod z Javą 8 (nadesłana przez @fredoverflow):
people.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
Chociaż ten kod jest prawie tak krótki, nie działa tak elegancko jak kod Scala.
W roztworze Scala The Seq[A]#sortBy
sposób przyjmuje funkcję A => B
, gdzie B
jest wymagane, aby miećOrdering
. Ordering
jest klasą typu. Pomyśl najlepiej o obu światach: tak jak Comparable
, jest to niejawne dla danego typu, ale podobnie Comparator
, jest rozszerzalne i może być dodane retrospektywnie do typów, które go nie miały. Ponieważ w Javie brakuje klas typów, musi ona powielać każdą taką metodę, raz na Comparable
, potem na Comparator
. Na przykład zobacz comparing
i thenComparing
tutaj .
Klasy typów pozwalają na pisanie reguł, takich jak „Jeśli A ma porządek, a B ma porządek, to ich krotka (A, B) również ma uporządkowanie”. W kodzie to znaczy:
implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl
W ten sposób sortBy
w naszym kodzie można porównać nazwę, a następnie wiek. Ta semantyka zostanie zakodowana powyższą „regułą”. Programista Scala intuicyjnie spodziewałby się, że to zadziała w ten sposób. Żadnych specjalnych metod, takich jak comparing
nie trzeba było dodawaćOrdering
.
Lambdy i odwołania do metod to tylko wierzchołek góry lodowej, jaką jest programowanie funkcjonalne. :)