В этой статье я указал и обсудил пять особенностей Java 8, которые кажутся мне более интересными.
- Трансляция и другие специальные функции
- Лямбда-выражения
- Параллельные операции
- движок JavaScript
- Новые API даты/времени
- Трансляция и другие специальные функции
Поток представляет собой последовательность элементов и поддерживает различные виды операций для выполнения вычислений над этими элементами:
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1"); myList .stream() .filter(s -> s.startsWith("c")) .map(String::toUpperCase) .sorted() .forEach(System.out::println); // C1 C2
-Потоковые операции бывают промежуточными или терминальными. Промежуточные операции возвращают поток, поэтому мы можем объединить несколько промежуточных операций без использования точки с запятой. Терминальные операции либо недействительны, либо возвращают непотоковые результаты. В приведенном выше примере filter, map и sorted являются промежуточными операциями, тогда как forEach — терминальной операцией.
Разные виды потоков
Потоки можно создавать из различных источников данных, особенно коллекций. Списки и наборы поддерживают новые методы stream() и parallelStream() для создания последовательного или параллельного потока.
//Prepare stream from collection List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1"); myList.stream() //Create a stream from a bunch of object references Stream.of("d2", "a2", "b1", "b3", "c") //Primitive streams (IntStream,LongStream and DoubleStream) IntStream.range(1, 4)
Другая особенность
Поддержка расширенных аннотаций
Можно аннотировать практически все: локальные переменные, универсальные типы, суперклассы и интерфейсы реализации, даже объявление исключений метода.
public class Annotations { @Retention( RetentionPolicy.RUNTIME ) @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } ) public @interface NonEmpty { } public static class Holder< @NonEmpty T > extends @NonEmpty Object { public void method() throws @NonEmpty Exception { } } public static void main(String[] args) { final Holder< String > holder = new @NonEmpty Holder< String >(); @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>(); } }
Внутренняя и внешняя итерация
Внешняя итерация (java7) - где коллекция должна быть реализована с помощью Iterable, чтобы итератор мог перечислять свои элементы, а клиенты использовали это для последовательного прохождения элементов коллекции.
List<String> alphabets = Arrays.asList(new String[]{"a","b","b","d"}); Iterator<String> iterator = alphabets.listIterator(); while(iterator.hasNext()){ System.out.println(iterator.next().toUpperCase()); } for(String letter: alphabets){ System.out.println(letter.toUpperCase()); }
У внешних итераторов могут быть вещи для очистки (например, поток, переменная итератора)
Внутренняя итерация (java8):
alphabets.forEach(l -> l.toUpperCase());
Преимуществом внутреннего итератора является возможность реализации атомарной групповой операции над элементами коллекции.
Ссылки на методы
Ссылки на методы предоставляют полезный синтаксис для прямого обращения к существующим методам или конструкторам классов или объектов Java (экземпляров).
class Car { public static Car create( final Supplier< Car > supplier ) { return supplier.get(); } public void running() { System.out.println( "Repaired " + this.toString() ); } } Car car = Car.create( Car::new ); List< Car > cars = Arrays.asList( car ); cars.forEach(Car::running);
Лямбда-выражения (,) –›{ ; }
Какими могут быть параметры метода?
java7: экземпляр любого класса, тип класса, переменная, константа, примитивы, объекты.
java8: функциональное выражение + параметры java7
Эти функциональные выражения мы назовем его лямбда-выражением.
Лямбда-выражения позволяют более компактно выражать экземпляры интерфейсов с одним методом (другое имя: функциональные интерфейсы).
@FunctionalInterface public interface Operation{ public Object doOperation(Object param1,Object param2); }
Реализация вышеуказанного интерфейса может быть написана следующим образом:
Operation instance= (value1,value2) -> { return param1 + param2; }
Lambda может быть представлена в виде списка параметров, разделенных запятыми–›, символа и тела.
Java 8 расширяет объявления интерфейса двумя новыми концепциями: методы по умолчанию и статические методы.
Методы интерфейса по умолчанию
@FunctionalInterface public interface FunctionalDefaultMethods { void method(); default void defaultMethod() { System.out.println("Default implementation"); } }
FunctionalDefaultMethods functionDefaultMethods=()-›{ System.out.println("моя реализация"); };
Статические методы интерфейса
@FunctionalInterface public interface FunctionalStaticMethods { void method(); static void defaultMethod() { System.out.println("Default implementation"); } }
FunctionalStaticMethods functionStaticMethods=()-›{ System.out.println("моя реализация"); };
Параллелизм
В версии Java 8 добавлено множество новых методов, позволяющих обрабатывать параллельные массивы. Возможно, самым важным из них является parallelSort(), который может значительно ускорить сортировку на многоядерных машинах.
long[] arrayOfLong = new long [ 20000 ]; Arrays.parallelSetAll( arrayOfLong, index -> ThreadLocalRandom.current().nextInt( 1000000 ) ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); Arrays.parallelSort( arrayOfLong ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) );
* метод parallelSetAll() для заполнения массивов 20000 случайных значений. После этого применяется parallelSort(). Программа выводит первые 10 элементов до и после сортировки, чтобы убедиться, что массив действительно упорядочен.
Параллелизм в коллекции
List<String> myList={..} myList.parallelStream().<operation> myList.stream().parallel() IntStream.range(1,20000).parallel().filter( this::isPrime).count()
… больше информации о параллелизме (количество потоков, размер пула и т. д.)
Общий пул ForkJoinPool = ForkJoinPool.commonPool();
движок Nashorn JavaScript
Java 8 поставляется с новым движком Nashorn JavaScript, который позволяет разрабатывать и запускать определенные виды приложений JavaScript на JVM. Движок Nashorn JavaScript — это просто еще одна реализация javax. script.ScriptEngine и следует тому же набору правил, что обеспечивает совместимость Java и JavaScript.
jjs – это автономный движок Nashorn, работающий из командной строки. Он принимает список файлов исходного кода JavaScript в качестве аргументов и запускает их.
API даты/времени
Новый API Date-Time в Java 8 находился под сильным влиянием Joda-Time и взял от него лучшее. Новый пакет java.time содержит все классы для работы с датой, временем, датой/временем, часовыми поясами, моментами времени, длительностью и часами.
LocalDate date = LocalDate.now(); LocalTime time = LocalTime.now(); LocalDateTime datetime = LocalDateTime.now(); ZonedDateTime zonedDatetime = ZonedDateTime.now(); /*ZoneId.of( "America/Los_Angeles" )*/ dateObject.plusDays(10); dateObject.minusWeeks(3); //Parsing LocalDateTime dt = LocalDateTime.parse("27::Apr::2014 21::39::48", DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss")); //Formating dt.format(DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss");
нажмите здесь, чтобы получить образец проекта, который я разработал с помощью Netbeans 8.0.2. Этот пример проекта охватывает почти все темы в этом блоге.
Что дальше?
Конечно, Java 9 (надеюсь, в 2016 г.)
Читайте похожие статьи от Келено
Следите за нами в Linkedin