Статьи

Игра с Java 8 лямбд в JDT

Чувак старого кудряща, который знает болтун

старый скряга Чувак, который знает Smalltalk

Я немного поигрался с языком, пока возился с поддержкой Java 8, разрабатываемой проектом Eclipse Java development tools (JDT).

Я признаю, что я немного не в восторге от лямбд в Java 8 . Это, конечно, исходит от Старого Чувака, Который знает Smalltalk (и LISP / Scheme).

Как и любой хороший придурок Smalltalk, когда я начал изучать, как использовать лямбды, я, естественно, решил реализовать известные и любимые коллекции.

Начиная примерно так:

1
2
3
4
5
6
7
8
9
OrderedCollection employees = new OrderedCollection();
employees.add(new Employee("Wayne", 10));
employees.add(new Employee("Joel", 9));
employees.add(new Employee("Jon", 6));
employees.add(new Employee("Anthony", 8));
employees.add(new Employee("Mary", 2));
employees.add(new Employee("Sue", 3));
employees.add(new Employee("Joanne", 7));
employees.add(new Employee("Shridar", 1));

В классической Java вы могли бы сделать что-то подобное, чтобы найти сотрудников с более чем пятилетним опытом работы:

1
2
3
List longTerm = new ArrayList();
for(Employee employee : employees)
    if (employee.years > 5) longTerm.add(employee);

Используя лямбды, вы можете сделать что-то вроде этого:

1
2
OrderedCollection longTerm =
    employees.select(employee -> employee.years > 5);

Это немного труднее, чем классическая Java, и я лично нахожу это очень читабельным и понятным; у читателей с разным опытом может быть другой вариант. Я считаю, что это намного лучше, чем эквивалентная реализация с анонимным классом:

1
2
3
4
5
6
OrderedCollection longTerm = employees.select(new SelectBlock() {
    @Override
    public boolean value(Employee employee) {
        return employee.years > 5;
    }
});

Анонимные занятия заставляют детей плакать.

Конечно, дети тоже не особенно рады реализации select() :

01
02
03
04
05
06
07
08
09
10
11
public class OrderedCollection<T> extends ArrayList<T> {
    ...
    public OrderedCollection<T> select(SelectBlock<T> block) {
        OrderedCollection<T> select = new OrderedCollection<T>();
        for(T value : this) {
            if (block.value(value)) select.add(value);
        }
        return select;
    }
    ...
}

Лямбды являются синтаксическим сахаром для анонимных классов и, возможно, облегчают чтение некоторого кода. Для моего довольно упрощенного примера преимущество по сравнению с прямым использованием for -loop незначительно с точки зрения читабельности, но его гораздо легче понять, чем пример анонимного класса. С точки зрения производительности, я ожидаю, что использование лямбда-выражений или анонимных классов в этом контексте будет на порядок хуже, чем использование for -loop.

Одна из самых интересных вещей, которые мы делаем в Smalltalk, — это создание собственных управляющих структур. Вместо создания совершенно новой коллекции вы можете создать собственные итераторы, например:

1
payroll.longTermEmployeesDo(employee -> payroll.giveEmployeeARaise(employee));

Или что-то вроде того. Я не уверен, если это делает это лучше или нет.

Простые коллекции могут быть не лучшим использованием лямбд. Лямбды не так полезны (или, как я считаю, эффективнее), как блоки в Smalltalk . Мне нужно потратить немного больше времени на изучение примеров, когда использование анонимных классов более естественно в Java ( Runnable s и слушатели кажутся очевидным местом для начала).

К сожалению, я думаю, что попытка реализовать подобные Smalltalk коллекции с использованием лямбд в Java 8 также заставит детей плакать.

Как прощальный выстрел … попробуйте обернуть свой мозг вокруг этого:

1
2
double average = (double)employees.inject(0,
    (sum, employee) -> sum + employee.years) / employees.size();

Полностью читабельный. Полностью.

Изменено 18 февраля 2014 г. Мои первые наблюдения заставили меня поверить, что лямбды — это синтаксический сахар для анонимных классов. С тех пор я узнал, что это не так. Далее, есть некоторые оптимизации, которые мне нужно лучше понять. Я вычеркнул неправильные утверждения (но в остальном оставил это для потомков).

Ссылка: игра с Java 8 Lambdas в JDT от нашего партнера по JCG Уэйна Битона в блоге Eclipse Hints, Tips и Random Musings .