Я немного поигрался с языком, пока возился с поддержкой Java 8, разрабатываемой проектом Eclipse Java development tools (JDT).
Я признаю, что я немного не в восторге от лямбд в Java 8 . Это, конечно, исходит от Старого Чувака, Который знает Smalltalk (и LISP / Scheme).
Как и любой хороший придурок Smalltalk, когда я начал изучать, как использовать лямбды, я, естественно, решил реализовать известные и любимые коллекции.
Начиная примерно так:
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 вы могли бы сделать что-то вроде этого, чтобы найти сотрудников с опытом работы более пяти лет:
List longTerm = new ArrayList(); for(Employee employee : employees) if (employee.years > 5) longTerm.add(employee);
Используя лямбды, вы можете сделать что-то вроде этого:
OrderedCollection longTerm = employees.select(employee -> employee.years > 5);
Это немного труднее, чем классическая Java, и я лично нахожу это очень читабельным и понятным у читателей с разным опытом может быть другой вариант. Я считаю, что это намного лучше, чем эквивалентная реализация с анонимным классом:
OrderedCollection longTerm = employees.select(new SelectBlock() { @Override public boolean value(Employee employee) { return employee.years > 5; } });
Анонимные занятия заставляют детей плакать.
Конечно, дети не особенно рады реализации select()
:
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 незначительно с точки зрения читабельности, но его гораздо легче понять, чем пример анонимного класса. С точки зрения производительности, я ожидаю, что использование lambdas или анонимных классов в этом контексте будет на порядок хуже, чем просто использование for
-loop.
Одна из самых интересных вещей, которые мы делаем в Smalltalk, — это создание собственных управляющих структур. Вместо создания совершенно новой коллекции вы можете создать собственные итераторы, например:
payroll.longTermEmployeesDo(employee -> payroll.giveEmployeeARaise(employee));
Или что-то вроде того. Я не уверен, если это делает это лучше или нет.
Простые коллекции могут быть не лучшим использованием лямбд. Лямбды не так полезны (или, как я считаю, эффективнее), как блоки в Smalltalk . Мне нужно потратить немного больше времени на изучение примеров, когда использование анонимных классов более естественно в Java ( Runnable
s и слушатели кажутся очевидным местом для начала).
К сожалению, я думаю, что попытка реализовать подобные Smalltalk коллекции с использованием лямбд в Java 8 также заставит детей плакать.
Как прощальный выстрел … попробуйте обернуть свой мозг вокруг этого:
double average = (double)employees.inject(0, (sum, employee) -> sum + employee.years) / employees.size();
Полностью читабельный. Полностью.