Ни для кого не секрет, что во второй половине 2013 года планируется выпуск Java 8 (UPD: на JavaOne 2013 в Москве сообщили, что выход восьмерки перенесут на 2014). Мне наконец-то надоело быть пассивным читателем всех этих многочисленных восторженных отзывов о нововведениях языка и я решил скачать предварительную версию JDK (благо она уже давно выложена) и начать свои экзерсисы.
Как правило я стараюсь ждать релиза, но сейчас в новостях столько разговоров о лямбда-выражениях в новой Java, что мне, старому Scala-фанатику и функционального программирования, уж очень сильно захотелось поиграться с новыми возможностями языка. Если смотреть на все новшества восьмой Java со стороны Scala программиста, то в целом лично я отношусь к ним положительно, поскольку такой расклад возможно приведет к уменьшению разрыва между мощью синтаксиса Scala и текущей (седьмой) версией Java как языка программирования. Хотя конечно, даже со всеми новшествами восьмерки Java будет сильно отставать от Scala.
JDK с “Lambda Project” можно скачать c официальной страницы.
Также в текущей сборке JDK 8 (на момент написания статьи) лямбды уже тоже есть, но API с коллекциями еще не полностью завершены.
Целью данной статьи не написание учебного пособия по новым функциям Java, думаю этой работой должны заниматься ребята из Oracle. Здесь я хотел сделать небольшие заметки для себя на будущее вместе с небольшими примерами кода, к которым хотелось бы вернуться после официального выпуска JDK 8.
В бытовом, чисто утилитарном смысле, под этой пресловутой лямбдой (или лямбда-выражениями) многие программисты как правило подразумевают обычные анонимные функции (хотя конечно это не строгое определение). Причем под функцией имеется в виду первоклассный объект. Его можно передавать как объект в аргументы метода, присваивать какой-то переменной и т.д. С точки зрения конечного пользователя (в нашем случае программиста) мы получаем удобный способ сокращать количество строк кода, без сильной потери в его читаемости.
Мои опыты
Один из самых часто встречаемых примеров в интернете, демонстрирующих пользу от использования лямбды — замена старых добрых анонимных классов.
Сравните. Это новый вариант:
// Вот она, анонимная функция!
Runnable r = () -> System.out.println("hello");
Thread th = new Thread(r);
th.start();
Вот так по-старинке:
Runnable r = new Runnable() {
public void run() {
System.out.println("hello");
}
};
Thread th = new Thread(r);
th.start();
Естественно и логично применить такой подход для слушателей.
Вот небольшой сниппет с формочкой и кнопкой.
public class Main {
public static void foo(ActionEvent e) {
System.out.println("hello:" + e);
}
public static void main(String arg[]) throws Exception {
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Hello");
// магия происходит здесь
button.addActionListener((ActionEvent e)-> { foo(e); });
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
Если у вас аллергия на вложенные скобки, то можно упростить следующим образом:
// Можно присвоить listener-у
ActionListener listener = (ActionEvent e)->{ foo(e); };
// а вот так не скомпилируется ;)
//Object o = (ActionEvent e) -> { foo(e); };
button.addActionListener(listener);
Или даже можно сделать так:
button.addActionListener(Main::foo);
Главное никаких отражений, используется invokedynamic.
Естественно возникает желание посмотреть на API коллекций.
Можно использовать в качестве Comparator-а функцию сортировщик:
String arr[] = {"a","b","c"};
Arrays.sort(arr, (x, y) -> x.compareToIgnoreCase(y));
Также в Java 8 будет реализация многопоточной сортировки:
String arr[] = {"a","b","c"};
Arrays.parallelSort(arr, (x, y) -> x.compareToIgnoreCase(y));
Функциональщики как раз любят такие многопоточные методы. К сожалению, на моих тестах в используемой версии JDK 8 от использования parallelSort польза была только на примитивных данных (например при сортировки массивов int-ов). На массивах с объектами никакой пользы не было, но ведь и релиз только через несколько месяцев, так что сейчас никаких серьезных тестов скорости проводить некорректно.
Итог
Думаю многие согласятся, что восьмерка не скоро будет тотально доминировать на серверах и использоваться в промышленной эксплуатации, поскольку существует довольно большая прослойки особо консервативных Java-программистов. Тем не менее функциональщина сейчас в мировом программистком тренде, поэтому Java 8 это безусловно интересно и имеет смысл потратить в дальнейшем дополнительное время на её изучение.