Ни для кого не секрет, что во второй половине 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 это безусловно интересно и имеет смысл потратить в дальнейшем дополнительное время на её изучение.