Статьи

Java 8: сортировка значений в коллекциях

Поняв, что Java 8 должна быть выпущена GA в течение следующих нескольких недель, я подумал, что пришло время взглянуть на нее и за последнюю неделю читал книгу Венката Субраманиама .

Я до главы 3, которая охватывает сортировку людей. Класс Person определяется примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
static class Person {
    private String name;
    private int age;
 
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    @Override
    public String toString() {
        return String.format("Person{name='%s', age=%d}", name, age);
    }
}

В первом примере мы берем список людей, а затем сортируем их по возрастанию:

1
2
List<Person> people = Arrays.asList(new Person("Paul", 24), new Person("Mark", 30), new Person("Will", 28));
people.stream().sorted((p1, p2) -> p1.age - p2.age).forEach(System.out::println);
1
2
3
Person{name='Paul', age=24}
Person{name='Will', age=28}
Person{name='Mark', age=30}

Если бы мы написали функцию, которая делала бы то же самое в Java 7, это выглядело бы так:

01
02
03
04
05
06
07
08
09
10
Collections.sort(people, new Comparator<Person>() {
    @Override
    public int compare(Person o1, Person o2) {
        return o1.age - o2.age;
    }
});
 
for (Person person : people) {
    System.out.println(person);
}

Java 8 сократила объем кода, который мы должны написать, хотя он все еще сложнее, чем то, что мы могли бы сделать в Ruby:

1
2
3
> people = [ {:name => "Paul", :age => 24}, {:name => "Mark", :age => 30}, {:name => "Will", :age => 28}]
> people.sort_by { |p| p[:age] }
=> [{:name=>"Paul", :age=>24}, {:name=>"Will", :age=>28}, {:name=>"Mark", :age=>30}]

Через несколько страниц Venkat показывает, как вы можете приблизиться к этому с помощью функции сравнения Comparator # :

1
2
Function<Person, Integer> byAge = p -> p.age ;
people.stream().sorted(comparing(byAge)).forEach(System.out::println);

Я думал, что мог бы сделать это проще, вставив лямбду ‘byAge’ следующим образом:

1
people.stream().sorted(comparing(p -> p.age)).forEach(System.out::println);

Кажется, что это компилируется и работает правильно, хотя IntelliJ 13.0 предполагает, что существует проблема « циклического вывода ». IntelliJ рад, если мы явно приведем лямбду следующим образом:

1
people.stream().sorted(comparing((Function<Person, Integer>) p -> p.age)).forEach(System.out::println);

IntelliJ также выглядит счастливым, если мы явно введем «p» в лямбда-выражении, поэтому я думаю, что на этом я пока остановлюсь:

1
people.stream().sorted(comparing((Person p) -> p.age)).forEach(System.out::println);