[Перевод] Размышления о Java 8 и Java 11 в ожидании Java 17
В мире Java есть одна приятная особенность, которая связана с жизненным циклом версий платформы. А именно, новый релиз Java выходит каждые 6 месяцев, а каждые 3 года появляется новый LTS-релиз — версия с долгосрочной поддержкой. В настоящий момент LTS-версия платформы представлена Java 11. Поэтому многие компании переходят на неё. Это — заметное движение, так как среди его последствий можно отметить тот факт, что, с выходом в сентябре 2021 года Java 17, новые фреймворки не будут поддерживать Java 8, а в качестве минимальной версии платформы будут рассматривать Java 11.
Цель этой статьи заключается в том, чтобы рассмотреть некоторые общие базовые API Java 8 и Java 11.
В Java 8, в пакете java.util.function
, появились новые интерфейсы, актуальные и в Java 11. Мы рассмотрим четыре таких интерфейса:
- Function
- Predicate
- Supplier
- Consumer
Интерфейс
Function
представляет функцию, которая принимает один аргумент и выдаёт некий результат: import java.util.function.Function;
public class FunctionApp {
public static void main(String[] args) {
Function toNumber = Integer::parseInt;
System.out.println("To number: " + toNumber.apply("234"));
Function upperCase = String::toUpperCase;
Function trim = String::trim;
Function searchEngine = upperCase.andThen(trim);
System.out.println("Search result: " + searchEngine.apply(" test one two "));
}
}
Интерфейс
Predicate
представляет предикат (логическую функцию) от одного аргумента: import java.util.function.Predicate;
public class PredicateApp {
public static void main(String[] args) {
Predicate startWithA = s -> s.startsWith("A");
Predicate startWithB = s -> s.startsWith("B");
System.out.println(startWithA.and(startWithB).test("Animal"));
}
}
Интерфейс
Supplier
представляет функцию, не принимающую никаких аргументов, но возвращающую некое значение: import java.util.Optional;
import java.util.function.Supplier;
public class SupplierApp {
public static void main(String[] args) {
Supplier cache = () -> "From Database";
Optional query = Optional.empty();
System.out.println(query.orElseGet(cache));
}
}
Интерфейс
Consumer
представляет функцию, которая принимает единственное входное значение, но ничего не возвращает: import java.util.function.Consumer;
public class ConsumerApp {
public static void main(String[] args) {
Consumer log = s -> System.out.println("The log " +s);
Consumer logB = s -> System.out.println("The logB " +s);
log.andThen(logB).accept("The value A");
}
}
Если продолжить разговор о функциональных интерфейсах, то можно сказать, что с ними связаны некоторые усовершенствования Java, например — улучшения в реализациях коллекций:
public class ListApp {
public static void main(String[] args) {
List fruits = new ArrayList<>(List.of("Bananas", "Melon", "Watermelon"));
fruits.forEach(System.out::println);
fruits.removeIf("Bananas"::equals);
fruits.sort(Comparator.naturalOrder());
System.out.println("After sort: ");
fruits.forEach(System.out::println);
}
}
public class SetApp {
public static void main(String[] args) {
Set fruits = new HashSet<>(List.of("Bananas", "Melon", "Watermelon"));
fruits.forEach(System.out::println);
fruits.removeIf("Bananas"::equals);
System.out.println("After sort: ");
fruits.forEach(System.out::println);
}
}
public class MapApp {
public static void main(String[] args) {
Map medias = new HashMap<>();
medias.put("facebook", "otaviojava");
medias.put("twitter", "otaviojava");
medias.put("linkedin", "otaviojava");
System.out.println("The medias values " + medias);
medias.forEach((k, v) -> System.out.println("the key: " + k + " the value " + v));
medias.compute("twitter", (k, v) -> k + '-' + v);
System.out.println("The medias values " + medias);
medias.computeIfAbsent("social", k -> "no media found: " + k);
medias.computeIfPresent("social", (k, v) -> k + " " + v);
System.out.println("The medias values " + medias);
medias.replaceAll((k, v) -> v.toUpperCase(Locale.ENGLISH));
System.out.println("The medias values " + medias);
}
}
Существуют, кроме того, новые фабричные методы, упрощающие создание интерфейсов коллекций:
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MethodFactory {
public static void main(String[] args) {
List fruits = List.of("banana", "apples");
Set animals = Set.of("Lion", "Monkey");
Map contacts = Map.of("email", "me@gmail.com", "twitter", "otaviojava");
}
}
Потоки — это последовательности элементов, поддерживающие последовательные и параллельные операции. Потоки в Java можно сравнить с движением воды в водопаде или в реке. Соответствующий API представляет собой надёжный и понятный механизм для работы с коллекциями:
public class StreamApp {
public static void main(String[] args) {
List fruits = List.of("Banana", "Melon", "Watermelon");
fruits.stream().sorted().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
fruits.stream().sorted().collect(Collectors.toUnmodifiableList());
Map> startWithB = fruits.stream().collect(Collectors.partitioningBy(f -> f.startsWith("B")));
System.out.println("Start with B " + startWithB);
Map> initials = fruits.stream().collect(Collectors.groupingBy(s -> s.substring(0)));
System.out.println("Initials: " + initials);
}
}
Вот ещё пример:
public class StreamReduceApp {
public static void main(String[] args) {
List values = List.of(BigDecimal.ONE, BigDecimal.TEN);
Optional total = values.stream().reduce(BigDecimal::add);
System.out.println(total);
}
}
Когда вышла платформа Java 8 — был представлен и новый API для работы с датой и временем (пакет
java.time
), появились новые типы, иммутабельные классы, методы, и, наконец, перечисления. Использование этих перечислений повышает удобство работы с днями недели и месяцами в сравнении с применением их числовых представлений.import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Year;
import java.time.YearMonth;
import java.util.Arrays;
public class DateApp {
public static void main(String[] args) {
System.out.println("LocalDateTime: " + LocalDateTime.now());
System.out.println("Localdate: " + LocalDate.now());
System.out.println("LocalDateTime: " + LocalDateTime.now());
System.out.println("YearMonth: " + YearMonth.now());
System.out.println("Year: " + Year.now());
System.out.println("Days of weeks: " + Arrays.toString(DayOfWeek.values()));
System.out.println("Months: " + Arrays.toString(Month.values()));
}
}
В текущем LTS-релизе платформы, в Java 11, имеются некоторые особенности, упрощающие жизнь разработчиков. Надо отметить, что тут мы лишь очень кратко рассмотрели некоторые особенности Java 8 и Java 11. А если говорить о возможностях, появлявшихся в различных версиях Java, то можно отметить, что существует множество материалов, раскрывающих эти особенности. Например — вот материал о новых возможностях Java 11.
Как вы готовитесь к выходу Java 17?