Завдання:
У вас є список people
об'єктів класу, у Person
яких є поля name
та age
. Ваше завдання - сортувати цей список спочатку name
, а потім за 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))
Оновлення
З того часу, як я написав цю відповідь, було досягнуто певного прогресу. Лямбди (та методичні посилання) нарешті висадилися на Яві, і вони штурмують світ Яви.
Ось як виглядатиме наведений вище код у Java 8 (надає @fredoverflow):
people.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
Хоча цей код майже такий короткий, він працює не так елегантно, як у Scala.
У розчині Scala, то Seq[A]#sortBy
метод приймає функцію , A => B
де B
потрібно , щоб матиOrdering
. Ordering
це тип-клас. Подумайте найкраще з обох світів: Мовляв Comparable
, це неявно для відповідного типу, але, схоже Comparator
, він розширюваний і може бути доданий ретроспективно до типів, яких у нього не було. Оскільки Java не має класів типів, вона повинна дублювати кожен такий метод, раз для Comparable
, потім для Comparator
. Наприклад, дивіться comparing
і thenComparing
тут .
Класи типів дозволяють писати правила типу "Якщо A має впорядкування, а B - впорядкування, то їх кортеж (A, B) також має впорядкування". У коді, тобто:
implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl
Ось як sortBy
в нашому коді можна порівняти за іменем, а потім за віком. Ця семантика буде закодована за допомогою вищезазначеного "правила". Програміст Scala інтуїтивно очікував, що це буде працювати таким чином. Жодних спеціальних методів, таких як comparing
доводилося додавати Ordering
.
Ламбдас і методичні посилання - лише підказка айсберга, що є функціональним програмуванням. :)