Корпорация Oracle выпустила Java 8 18 марта 2014 года, которая предоставляет больше инструментов и концепций программирования для более быстрого и, что более важно, более лаконичного и удобного в сопровождении решения новых или существующих проблем. В этой статье в основном обобщаются концепции и использование потоковой обработки, лямбда-выражений и необязательных классов, в надежде помочь повысить эффективность разработки и уменьшить сложность кода.
потоковая обработка
Поток — это последовательность элементов данных, создающая только один элемент за раз. Программа может считывать элементы данных один за другим из входного потока, а затем таким же образом записывать элементы данных в выходной поток. Выходной поток одной программы, скорее всего, будет входным потоком другой программы.
Типичным примером является операция конвейера в системах Unix. Вывод одной команды может быть передан как ввод другой команды. Сложные функции могут быть выполнены с помощью коротких команд.
Например, следующая короткая строка команд реализует логику обработки чтения файлов, преобразования строчных букв, сортировки по словарю и получения последних трех букв.
cat file1 file2 | tr "[A-Z]" "[a-z]" | sort | tail -3`
структура
Потоки могут быть построены следующими распространенными способами:
Stream stream=Stream.of("H","E","L","L","O");
String [] strArray=new String[]{"H","E","L","L","O"};
stream=Stream.of(strArray);
stream=Arrays.stream(strArray);
List<String> list=Arrays.asList(strArray);
stream=list.stream();
действовать
Промежуточные операции: сопоставление, фильтрация, различение, сортировка, просмотр, ограничение, пропуск, параллельная, последовательная, неупорядоченная Терминальные операции: forEach, forEachOrdered, toArray, reduce, collect, min, max, count, anyMatch, allMatch, noneMatch, findFirst, findAny , итератор
пример
map
Операция карты может изменить содержимое или тип объекта, генерируя отображение один к одному, где каждый входной элемент преобразуется в другой элемент в соответствии с правилами. Например, преобразовать прописные буквы в строчные.
Java7
List<String> wordList=Arrays.asList("H","E","L","L","O");
List<String> outputList=new ArrayList<String>();
for(String word:wordList){
outputList.add(word.toLowerCase());
}
Java8
List<String> wordList=Arrays.asList("H","E","L","L","O");
List<String> outputList=wordList.stream().map(String::toLowerCase).collect(Collectors.toList());
flatmap
flatmap обеспечивает сопоставление отношений «один ко многим».
List<String> hiList = Arrays.asList("hello", "hi", "你好");
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
hiList.stream().flatMap(hi -> nameList.stream().map(name -> hi + " " + name)).collect(Collectors.toList()).forEach(System.out::println);
filter
Фильтр дает тест для исходного потока, который остается для генерации нового потока через тестовый элемент.
Java7
Integer[] nums={0,1,2,3,4,5,6,7,8,9};
List<Integer> oddNums=new ArrayList<Integer>();
for(Integer num:nums){
if((num&1)==1){
oddNums.add(num);
}
}
Java8
Integer[] nums={0,1,2,3,4,5,6,7,8,9};
List<Integer> oddNums= Stream.of(nums).filter(n->(n&1)==1).collect(Collectors.toList());
foreach
Метод forEach принимает лямбда-выражение и выполняет его для каждого элемента потока.
Java7
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
for(String name:nameList){
System.out.println(name);
}
Java8
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
nameList.stream().forEach(System.out::println);
max
max находит наибольшее число.
Java7
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
Integer maxLen=Integer.MIN_VALUE;
for(String name:nameList){
if(maxLen.compareTo(name.length())<0){
maxLen=name.length();
}
}
Java8
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
nameList.stream().mapToInt(String::length).max();
Лямбда-выражения
Лямбда-выражение можно понимать как краткий способ выражения передаваемой анонимной функции: у него нет имени, но есть список параметров, тело функции, тип возвращаемого значения и, возможно, список исключений, которые могут быть выброшены.
-
функция. Лямбда-функции не принадлежат к определенному классу, как это делают методы. Но, как и у методов, есть список параметров, тело функции, тип возвращаемого значения и, возможно, список исключений, которые могут быть выброшены.
-
передача. Лямбда-выражения можно передавать в качестве параметров методам или хранить в переменных.
-
краткий Не нужно писать много шаблонов, как анонимные классы.
Лямбда-выражения можно использовать в функциональных интерфейсах.
Функциональный интерфейс — это интерфейс, определяющий только один абстрактный метод.
public interface Comparator<T>{
int compare(T o1,T o2);
}
пример
Java7
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
nameList.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
Java8
List<String> nameList = Arrays.asList("Ted", "Bobo", "Alice");
nameList.sort((String o1,String o2)->o1.compareTo(o2));
Необязательный класс
Основная проблема, которую решает класс Optional, — печально известное исключение NullPointerException.
По сути, необязательно - это класс обертки, который содержит необязательные значения, что означает, что дополнительный класс может либо содержать объекты, либо быть пустым.
структура
объявить пустой необязательный
Optional<Car> optCar=Optional.empty();
Создать необязательное значение из ненулевого значения
Optional<Car> optCar=Optional.of(car);
Необязательный, который принимает null
Optional<Car> optCar=Optional.ofNullable(car);
метод
get()
Если переменная существует, она возвращает инкапсулированное значение переменной напрямую, в противном случае создается исключение NoSuchElementException.
orElse(T other)
Это позволяет указать значение по умолчанию, когда необязательный объект не содержит значения.
orElseGet(Supplier<? extends T> other)
Он позволяет выполнять метод по умолчанию и возвращать соответствующее значение, когда необязательный объект не содержит значения.
orElseThrow(Supplier<? extends X> exceptionSupplier)
Это позволяет вам генерировать указанное исключение, если необязательный объект не содержит значения
ifPresent(Consumer<? super T>)
Выполняет метод, переданный в качестве параметра, если значение переменной существует, в противном случае ничего не делает.
пример
Java7
public static String getName(User u) {
if (u == null)
return "Unknown";
return u.name;
}
Java8
public static String getName(User u) {
return Optional.ofNullable(u)
.map(user->user.name)
.orElse("Unknown");
}
использованная литература
- "Java8 бой"
- Woohoo. IBM.com/developer Я…