В наши дни много функциональной ажиотажа, поэтому я бы дал краткий обзор того, что там есть, по крайней мере, когда речь идет о коллекциях в Java. Лично мне нравится стандарт
API коллекций, но в некоторых случаях это может быть неудобно и добавлять дополнительную многословность. Это не должно быть проблемой в последней версии Java 8+. Там мы, вероятно, беспокоимся о том, чтобы не создавать ад-колбэк, но эй, для большинства вещей нет серебряной пули, почему она должна быть для программирования?
Путь гуавы
Проект Guava — одна из основных библиотек Google, в которой есть множество различных основных языковых аспектов и проблем. Существуют утилиты и расширения для повседневного использования, такие как: коллекции, примитивы, кэширование, общие аннотации, обработка строк, ввод-вывод, математика, отражения и многие другие. Мы только взглянем на вкусности Коллекций, поэтому давайте посмотрим на некоторые из них:
1
2
3
4
5
6
7
8
|
// list ImmutableList<String> of = ImmutableList.of( "a" , "b" , "c" , "d" ); // Same one for map ImmutableMap<String, String> map = ImmutableMap.of( "key1" , "value1" , "key2" , "value2" ); //list of ints List<Integer> theList = Ints.asList( 1 , 2 , 3 , 4 , 522 , 5 , 6 ); |
Коллекции Guava совместимы с коллекциями JDK, поскольку они в основном расширяют или реализуют стандартные классы. Есть несколько классных утилит, которые являются частью API и имеют схожие названия с именами из java.util.Collections . По сути, любой программист, который знает коллекции JDK, должен легко переносить их в Guava. Те, что для списка , называются списками , одна для набора — наборы, для карты — карты и так далее для остальных. Например:
01
02
03
04
05
06
07
08
09
10
11
|
//create new List List<someLongName> list = Lists.newArrayList(); //create new LinkedHashMap Map<someKeyType, SomeValueType> map = Maps.newLinkedHashMap(); //initalize Array List on the spot List<String> someList = Lists.newArrayList( "one" , "two" , "three" ); //set inital size for readability as well as performance List<Type> exactly100 = Lists.newArrayListWithCapacity( 100 ); List<Type> approx100 = Lists.newArrayListWithExpectedSize( 100 ); |
Методы, соответствующие определенному интерфейсу, сгруппированы очень интуитивно. Есть также несколько очень хороших способов построения кеша с различными функциями:
01
02
03
04
05
06
07
08
09
10
11
12
|
Cache<Integer, Customer> cache = CacheBuilder.newBuilder() .weakKeys() .maximumSize( 10000 ) .expireAfterWrite( 10 , TimeUnit.MINUTES) .build( new CacheLoader<Integer, Customer>() { @Override public Customer load(Integer key) throws Exception { return retreveCustomerForKey(key); } }); |
Так как Guava доступен в большинстве репозиториев Maven, очень легко добавить его в вашу сборку.
LAMBDAJ
Идея проекта заключается в том, чтобы манипулировать коллекциями функционально и статически. Это достигается таким образом, чтобы избежать повторений простых задач, которые мы обычно делаем с коллекциями. Повторение заставляет программистов выполнять копирование / вставку, а создание заставляет их создавать ошибки, делая это. Доступ к коллекциям без явного зацикливания предоставляет способ фильтрации, сортировки, извлечения, группировки, преобразования, вызова метода для каждого элемента или суммирования элементов или полей этих элементов в коллекциях. В дополнение ко всем этим функциям lambdaj также является своего рода DSL, так как он добавляет очень интересные «сахарные» функции в синтаксис, делая его более читабельным в псевдоанглийском. Это делается статическими методами, поэтому для их использования мы включаем их напрямую:
1
|
import static ch.lambdaj.Lambda.*; |
Что касается проверки и сопоставления, то лямбдаж сильно зависит от совпадений Hamcrest. Так, например, чтобы создать проверку для нечетных целых чисел, а затем отфильтровать список с этой проверкой:
1
2
3
4
5
6
|
Matcher<Integer> odd = new Predicate<Integer>() { public boolean apply(Integer item) { return item % 2 == 1 ; } }; List<Integer> oddNumbers = filter(odd, asList( 1 , 2 , 3 , 4 , 5 )); |
и, как ожидается, список вернет список [1,3,5]. Lambdaj делает шаг вперед с помощью DSL, например:
1
2
3
4
5
|
List<Beneficiary> beneficiaries = with(transactions) .retain(having(on(Transaction. class ) .getQunatity(), lessThan( 100 ))) .extract(on(Transaction. class ).getBeneficiary()) .sort(on(Beneficiary. class ).getName()); |
Расходы на исполнение
Хотя лучший способ сделать ваше приложение быстрым — иметь максимально чистый код, наступает момент, когда вы должны оптимизировать. Для этого есть некоторая информация, предоставленная создателями об использовании памяти и времени. У Lambdaj есть вики-страница о производительности с примерами кода. Есть также некоторые тесты, выполненные другими программистами, где они сравнивают, например, lambdaj с JDK8. Есть также некоторые измерения использования памяти Guava. Что касается производительности Guava, то большая часть его функциональных возможностей — стандартные компоновщики классов JDK и утилиты, поэтому накладные расходы минимальны. В конце концов, вам решать, насколько каждая из этих библиотек окажет влияние на ваш проект и будет ли это позитивно. Я за идею, что почти каждый проект должен иметь Guava на своем пути к классам.
Сводка по ссылкам
- Гуава http://code.google.com/p/guava-libraries/
- лямбдадж http://code.google.com/p/lambdaj/
- Hamcrest http://hamcrest.org/
- Ссылки на гуаву http://www.tfnico.com/presentations/google-guava
- Примеры гуавы https://github.com/mitemitreski/guava-examples
- Презентация гуавы http://blog.mitemitreski.com/2012/07/google-guava-for-cleaner-code.html
Ссылка: Функциональные коллекции Java от нашего партнера по JCG Мите Митрески в блоге Java Advent Calendar .