API, ради которых наконец-то стоит обновиться с Java 8. Часть 1 |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2020-02-09 19:42 На сегодняшний день Java 8 является самой популярной версией Java и ещё довольно долго будет ей оставаться. Однако с тех пор уже выпущено пять новых версий Java (9, 10, 11, 12, 13), и совсем скоро выйдет ещё одна, Java 14. В этих новых версиях появилось гигантское количество новых возможностей. Например, если считать в JEP'ах, то в сумме их было реализовано 141:
Однако в этом цикле статей не будет никакого сухого перечисления JEP'ов. Вместо этого я хочу просто рассказать об интересных API, которые появились в новых версиях. Каждая статья будет содержать по 10 API. В выборе и порядке этих API не будет какой-то определённой логики и закономерности. Это будет просто 10 случайных API, не ТОП 10 и без сортировки от наиболее важного API к наименее важному. Давайте начнём. 1. Методы Objects.requireNonNullElse() и Objects.requireNonNullElseGet() Появились в: Java 9 Начнём мы наш список с двух очень простеньких, но очень полезных методов в классе class MyCoder { private final Charset charset; MyCoder(Charset charset) { this.charset = Objects.requireNonNullElse( charset, StandardCharsets.UTF_8); } }
class MyCoder { private final Charset charset; MyCoder(Charset charset) { this.charset = Objects.requireNonNullElseGet( charset, MyCoder::defaultCharset); } private static Charset defaultCharset() { // long operation... } } Да, конечно же в обоих случаях можно было бы легко обойтись и без этих функций, например, использовать обычный тернарный оператор или 2. Методы-фабрики, возвращающие неизменяемые коллекции Появились в: Java 9 Если предыдущие два метода – это просто косметика, то статические методы-фабрики коллекций позволяют действительно сильно сократить код и даже улучшить его безопасность. Речь о следующих методах, появившихся в Java 9:
К этому же списку можно добавить сопутствующий метод
Статические методы-фабрики позволяют создать неизменяемую коллекцию и инициализировать её в одно действие: List<String> imageExtensions = List.of("bmp", "jpg", "png", "gif"); Если не пользоваться сторонними библиотеками, то аналогичный код на Java 8 выглядит гораздо более громоздким: List<String> imageExtensions = Collections.unmodifiableList( Arrays.asList("bmp", "jpg", "png", "gif")); А в случае с Такая громоздкость провоцирует многих людей, пишуших на Java 8, вообще отказываться от неизменяемых коллекций и всегда использовать обычные Если же наконец обновиться с Java 8, то работать с неизменяемыми коллекциями становится намного проще и приятнее благодаря методам-фабрикам. 3. Files.readString() и Files.writeString() Появились в: Java 11 Java всегда была известна своей неспешностью вводить готовые методы для частых операций. Например, для одной из самых востребованных операций в программировании, чтения файла, очень долго не было готового метода. Лишь спустя 15 лет после выхода Java 1.0 появилось NIO, где был введён метод Но этого всё ещё не хватало, потому что людям часто приходится работать с текстовыми файлами и для этого нужно читать из файла строки, а не байты. Поэтому в Java 8 добавили метод Однако и этого было недостаточно, так как люди спрашивали, как просто прочитать весь файл в виде одной строки. В итоге, для полноты картины в Java 11 добавили долгожданный метод Вместе с /** Перекодировать файл из одной кодировки в другую */ private void reencodeFile(Path path, Charset from, Charset to) throws IOException { String content = Files.readString(path, from); Files.writeString(path, content, to); } 4. Optional.ifPresentOrElse() и Optional.stream() Появились в: Java 9 Когда Optional<String> opt = ... if (opt.isPresent()) { log.info("Value = " + opt.get()); } else { log.error("Empty"); } Либо можно извернуться ещё таким образом: Optional<String> opt = ... opt.ifPresent(str -> log.info("Value = " + str)); if (opt.isEmpty()) { log.error("Empty"); } Оба варианта не идеальны. Но, начиная с Java 9, такое можно сделать элегантно с помощью метода Optional<String> opt = ... opt.ifPresentOrElse( str -> log.info("Value = " + str), () -> log.error("Empty")); Ещё одним новым интересным методом в Java 9 стал class Employee { Optional<String> getPhoneNumber() { ... } } class Department { List<Employee> getEmployees() { ... } } class Company { List<Department> getDepartments() { ... } Set<String> getAllPhoneNumbers() { return getDepartments() .stream() .flatMap(d -> d.getEmployees().stream()) .flatMap(e -> e.getPhoneNumber().stream()) .collect(Collectors.toSet()); } } В Java 8 пришлось бы писать что-нибудь вроде: e -> e.getPhoneNumber().map(Stream::of).orElse(Stream.empty()) Это выглядит громоздко и не очень читабельно. 5. Process.pid(), Process.info() и ProcessHandle Появились в: Java 9 Если без предыдущих API обойтись худо-бедно ещё можно, то вот замену метода Process process = Runtime.getRuntime().exec("java -version"); System.out.println(process.pid()); Также с помощью метода Process process = Runtime.getRuntime().exec("java -version"); ProcessHandle.Info info = process.info(); System.out.println("PID = " + process.pid()); System.out.println("User = " + info.user()); System.out.println("Command = " + info.command()); System.out.println("Args = " + info.arguments().map(Arrays::toString)); System.out.println("Command Line = " + info.commandLine()); System.out.println("Start Time = " + info.startInstant()); System.out.println("Total Time = " + info.totalCpuDuration()); Вывод: PID = 174 User = Optional[orionll] Command = Optional[/usr/lib/jvm/java-13-openjdk-amd64/bin/java] Args = Optional[[-version]] Command Line = Optional[/usr/lib/jvm/java-13-openjdk-amd64/bin/java -version] Start Time = Optional[2020-01-24T05:54:25.680Z] Total Time = Optional[PT0.01S] Что делать, если процесс был запущен не из текущего Java-процесса? Для этого на помощь приходит ProcessHandle handle = ProcessHandle.current(); ProcessHandle.Info info = handle.info(); System.out.println("PID = " + handle.pid()); System.out.println("User = " + info.user()); System.out.println("Command = " + info.command()); System.out.println("Args = " + info.arguments().map(Arrays::toString)); System.out.println("Command Line = " + info.commandLine()); System.out.println("Start Time = " + info.startInstant()); System.out.println("Total Time = " + info.totalCpuDuration()); Вывод: PID = 191 User = Optional[orionll] Command = Optional[/usr/lib/jvm/java-13-openjdk-amd64/bin/java] Args = Optional[[Main.java]] Command Line = Optional[/usr/lib/jvm/java-13-openjdk-amd64/bin/java Main.java] Start Time = Optional[2020-01-24T05:59:17.060Z] Total Time = Optional[PT1.56S] Чтобы получить Также в 6. Методы String: isBlank(), strip(), stripLeading(), stripTrailing(), repeat() и lines() Появились в: Java 11 Целая гора полезных методов для строк появилась в Java 11. Метод System.out.println(" ".isBlank()); // true Методы String str = " Hello, world! "; String str1 = str.stripLeading(); // "Hello, world! " String str2 = str.stripTrailing(); // " Hello, world!" String str3 = str.strip(); // "Hello, world!" Заметьте, что System.out.println("stru2000".strip()); // "str" System.out.println("stru2000".trim()); // "stru2000" Метод System.out.print("Hello, world! ".repeat(3)); Вывод: Hello, world! Hello, world! Hello, world! Наконец, метод System.out.println("line1 line2 line3 " .lines() .map(String::toUpperCase) .collect(Collectors.joining(" "))); Вывод: LINE1 LINE2 LINE3 7. String.indent() Появился в: Java 12 Давайте разбавим наш рассказ чем-нибудь свежим, что появилось совсем недавно. Встречайте: метод String body = "<h1>Title</h1> " + "<p>Hello, world!</p>"; System.out.println("<html> " + " <body> " + body.indent(4) + " </body> " + "</html>"); Вывод: <html> <body> <h1>Title</h1> <p>Hello, world!</p> </body> </html> Заметьте, что для последней линии Конечно, наибольшый интерес такой метод будет представлять в сочетании с блоками текста, когда они станут стабильными, но ничто не мешает использовать его уже прямо сейчас без всяких блоков текста. 8. Методы Stream: takeWhile(), dropWhile(), iterate() с предикатом и ofNullable() Появились в: Java 9
[ { "date" : "2020-01-27", "text" : "..." }, { "date" : "2020-01-25", "text" : "..." }, { "date" : "2020-01-22", "text" : "..." }, { "date" : "2020-01-17", "text" : "..." }, { "date" : "2020-01-11", "text" : "..." }, { "date" : "2020-01-02", "text" : "..." }, { "date" : "2019-12-30", "text" : "..." }, { "date" : "2019-12-27", "text" : "..." }, ... ]
getNotesStream() .takeWhile(note -> note.getDate().getYear() == 2020); А если мы хотим получить записи за 2019 год, то можно использовать getNotesStream() .dropWhile(note -> note.getDate().getYear() == 2020) .takeWhile(note -> note.getDate().getYear() == 2019); В Java 8 // Java 8 for (int i = 1; i < 100; i *= 2) { System.out.println(i); } // Java 9+ IntStream .iterate(1, i -> i < 100, i -> i * 2) .forEach(System.out::println); Обе этих версии печатают все степени двойки, которые не превышают 1 2 4 8 16 32 64 Кстати, последний код можно было бы переписать с использованием IntStream .iterate(1, i -> i * 2) .takeWhile(i -> i < 100) .forEach(System.out::println); Однако вариант с трёхаргументным Наконец, class Employee { String getPhoneNumber() { ... } } class Department { List<Employee> getEmployees() { ... } } class Company { List<Department> getDepartments() { ... } Set<String> getAllPhoneNumbers() { return getDepartments() .stream() .flatMap(d -> d.getEmployees().stream()) .flatMap(e -> Stream.ofNullable(e.getPhoneNumber())) .collect(Collectors.toSet()); } } 9. Predicate.not() Появился в: Java 11 Этот метод не вносит ничего принципиально нового и носит скорее косметический, нежели фундаментальный характер. И всё же возможность немного подсократить код всегда очень приятна. С помощью Files.lines(path) .filter(str -> !str.isEmpty()) .forEach(System.out::println); А теперь используя Files.lines(path) .filter(not(String::isEmpty)) .forEach(System.out::println); Да, экономия не такая уж и огромная, а если использовать 10. Cleaner Появился в: Java 9 Сегодняшний рассказ я хочу завершить новым интересным API, появившимся в Java 9 и служащим для очистки ресурсов перед их утилизацией сборщиком мусора. С помощью public class Resource implements Closeable { private static final Cleaner CLEANER = Cleaner.create(); private final Cleaner.Cleanable cleanable; public Resource() { cleanable = CLEANER.register(this, () -> { // Очищающее действие // (например, закрытие соединения) }); } @Override public void close() { cleanable.clean(); } } По-хорошему, такой ресурс пользователи должны создавать в блоке try (var resource = new Resource()) { // Используем ресурс } Однако могут найтись пользователи, которые забудут это делать и будут писать просто Если вы хотите изучить Заключение Java не стоит на месте и постепенно развивается. Пока вы сидите на Java 8, с каждым релизом появляется всё больше и больше новых интересных API. Сегодня мы рассмотрели 10 таких API. И вы сможете использовать их все, если наконец решитесь мигрировать с Java 8. В следующий раз мы рассмотрим ещё 10 новых API. Источник: habr.com Комментарии: |
|