Pull to refresh

LINQ for Java: LambdaJ

Reading time3 min
Views19K
Как часто вам приходилось видеть или писать одни и те же несколько строчек кода, которые постоянно используются вместе для решения одной и той же задачи? Взять, например, перебор или сортировку (некоторую манипуляцию) коллекций. Такие участки кода программистам приходится писать каждый день. Конечно, есть различные IDE, в которых можно использовать snippet'ы и шаблоны. Тем не менее, подобные конструкции загромождают код, делая его более подходящим для обработки компьютером, а не для восприятия программистом.

Тут нам на помощь приходит библиотека LambdaJ. Её предназначением является упрощение процесса работы с коллекциями с целью уменьшения ошибок в коде и повышения его читабельности путём реализации некоторых техник функционального программирования без пренебрежения статической типизацией данных. Последний факт крайне важен, так как статическая типизация является преимуществом языка, значительно повышающим надёжность кода.

Рассмотрим пример использования LambdaJ. Найдём возраст самого юного покупателя, который совершил покупку более, чем на 50'000.

Классический (итеративный) способ:
int age = Integer.MAX_VALUE;
for (Sale sale : sales) {
  if (sale.getCost() > 50000.00) {
    int buyerAge = sale.getBuyer().getAge();
    if (buyerAge < age)
      age = buyerAge;
  }
}


LambdaJ способ:
int age = min(forEach(select(sales, having(
  on(Sale.class).getCost(), greaterThan(50000.00)).getBuyer()))),
  on(Person.class).getAge());



Функциональность



Из вышеприведённого примера видно, что библиотека предоставляет программисту своего рода DSL для работы с коллекциями. Доменами в данном случае являются java-коллекции, а конструкциями языка — статически импортируемые методы соответствующих классов библиотеки LambdaJ.

Так что же умеет LambdaJ? Список фич примерно следующий:
  • фильтрация элементов по заданному условию;
  • изменение каждого элемента по заданному правилу;
  • получение заданного свойства из каждого элемента;
  • сортировка элементов на основе одного из свойств;
  • индексирование элементов на основе одного из свойств;
  • группировка элементов на основе одного или нескольких свойств;
  • вызов заданного метода для каждого элемента;
  • агрегация (например, суммирование) элементов или одного из их свойств;
  • проекция (копирование) свойств одного набора объектов в свойства другого набора объектов (Domain -> DTO);
  • конкатенация строкового представления элементов или одного из их свойств.
Сюда же можно добавить работу с замыканиями (хотя, на мой взгляд, тут лучше подождать Java 7).


Примеры



Фильтрация

List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
List<Person> oldFriends = filter(having(on(Person.class).getAge(), greaterThan(30)), meAndMyFriends);

Агрегация

int totalAge = sum(meAndMyFriends, on(Person.class).getAge());

Получение свойств

List<Integer> lengths = convert(strings, new PropertyExtractor("length"));
List<Integer> ages = extract(persons, on(Person.class).getAge());

Индексирование

Map<String, Person> personsByName = index(persons, on(Person.class).getFirstName());

Сортировка

List<Person> sorted = sort(persons, on(Person.class).getAge());

Группировка

Group<Person> group = group(meAndMyFriends, by(on(Person.class).getAge()));
Group<Person> group29aged = group.findGroup("29");


Производительность



Как известно, платой за удобство является производительность. В случае с LambdaJ overhead составляет в среднем 2,5 раза [*]. Это, безусловно, печально. Однако, если манипуляция коллекциями занимает незначительную часть процессорного времени работы вашего приложения, то плюсы от удобства работы могу значительно перевесит минус overhead'a.


P.S


Данная статья является вольным переводом произвольных частей официальной Wiki LambdaJ. Более подробную информацию можно найти там.
Tags:
Hubs:
+25
Comments24

Articles

Change theme settings