- Какие бывают операции в стримах? Напишите стрим?
- Что поменялось с Java 8 по Java <CURRENT_VERSION>?
- В какой кодировке строки в Java? Как хранятся строки внутри класса String? Как устроен String?
- Сколько в байт занимает каждый из примитивных типов в памяти? А объект?
- Какие ссылки бывают в Java?
Есть 2 вида операций в Java Stream
:
- Промежуточные (Intermediate) -
filter
,map
,sorted
,peek
и т.д. ВозвращаютStream
. - Терминальные (Terminal) -
collect
,forEach
,count
,reduce
,findFirst
,anyMatch
и т.д. Возвращают результат стрима и запускают его выполнение.
Кроме того, будет полезно ознакомиться с содержимым пакета java.util.stream и доступными коллекторами из Collectors.
Периодически просят написать какой-нибудь стрим, поэтому хорошо бы попрактиковаться. Можно на работе наесться, можно придумать задачи самому себе, можно поискать что-нибудь готовое:
- Java8 Code Kata
- Experience-Java-8
- Может быть даже курс - Java. Functional programming
Почитать подробнее про стримы лучше в Java Doc, но можно и в статьях:
- Java 8 Stream API
- The Java 8 Stream API Tutorial
- Полное руководство по Java 8 Stream API в картинках и примерах. Тут не просто в картинках, а в анимациях!
- Шпаргалка Java программиста 4. Java Stream API
- Java Stream API: что делает хорошо, а что не очень
- Пишем свой Spliterator
Посмотреть:
- На letsCode - Java Stream API: функционально, модно, молодёжно!
- Лекция в CSCenter от Тагира Валеева - Лекция 8. Stream API
- Доклад Тагира Валеева на Joker 2016 - Причуды Stream API
Java имеет богатую историю. На данный момент проекты чаще всего разделяются на:
- legacy-проекты с версией Java меньше 8
- проекты на Java 8, самая распрастранённая и популярная
- проекты на Java 9+ (точнее либо 11 LTS, либо последние полугодовые релизы)
Между 8 и 9 версиями случился небольшой разлом с частичной потерей обратной совместимости, а потом приколы лицензирования подъехали, поэтому миграция и в без того консервативном мире Java-приложений идёт медленно. Однако идёт, и если вы собеседуетесь в компанию, где этот переход уже осуществили, то, вероятно, у вас поинтересуются, что же там с Java 8 поменялось, чем живёт и дышит современная Java.
На момент выхода статьи, имеем:
- 9: Project Jigsaw aka Модули, HTTP/2 Client (Incubator), jshell, G1 GC по умолчанию, Compact Strings и другие.
- 10: Local-Variable Type Inference (var), Parallel Full GC для G1, Graal можно использовать как основной JIT-компилятор и другие.
- 11 LTS: var в лямбдах, компиляция и запуск single-file программ через java, новые методы для String, Epsilon GC (Experimental), ZGC (Experimental) и другие.
- 12: Switch Expressions (Preview), Shenandoah (Experimental), улучшения в G1, JMH и другие
- 13: Text Blocks (Preview) и другое
- 14: Pattern Matching для instanceof (Preview), Packaging Tool (Incubator), улучшили сообщение для NullPointerExceptions, Records (Preview) и другие.
- 15: Sealed Classes (Preview), Hidden Classes, удаление Nashorn JavaScript Engine из JDK и другие.
Найти ссылки на документацию к API, языку и виртуальной машине, release notes и сравнить API между версиями можно в Java-альманахе.
Кроме всего прочего, есть ряд проектов, в рамках которых развиваются большие и ожидаемые сообществом изменения Java:
- Amber - проект по реализации маленьких, но продуктивных улучшений языка Java. В рамках данного проекта постепенно реализуется и независимо выходит целый набор JEP: var (JDK 10), Switch Expressions, Sealed Types, Records, Text Blocks, Pattern Matching для instanceof и другие.
- Panama - проект по улучшению взаимодействия между JVM и нативным кодом. На Хабре есть статья с разъяснениями и интервью с Владимиром Ивановым на эту тему.
- Loom - проект по внедрению в Java легковесных потоков. На Хабре есть две прекрасные статьи с разъяснениями: раз и два.
- Valhalla - это проект по созданию нескольких больших и сложных улучшений языка и VM. В него входят: Inline types, Generics over Primitive Types, Enhanced volatiles и другие возможные или необходимые в рамках проекта улучшения.
- Lanai - проект по улучшению рендеринга настольных Java-приложений на MacOS путём использования Metal Apple platform API. C 14 мая 2020 появились Early-Access сборки.
- и другие
Отдельно нужно упомянуть GraalVM - это JDK и виртуальная машина Java, которая создана, чтобы объединить необъединяемое:
- быстрое выполнение Java
- уменьшение времени старта и потребления памяти для Java
- комбинирование и исполнение программ, написанных на различных ЯП, в том числе на платформо-зависимых
- общие инструменты для всех ЯП
- поддержка JIT и AOT-компиляции
- и т.п.
Послушать на тему:
- Два выпуска подкаста Javaswag: раз и два
- Выпуск 172 Java подкаста Подлодка, в гости к которому пришёл Тагир Валеев
Почитать на Хабре:
- Руководство по возможностям Java версий 8-14
- API, ради которых наконец-то стоит обновиться с Java 8. Часть 1
- JAVA 9. Что нового?
- Обзор Java 9
- Модульность в Java 9
- Компактные строки в Java 9
- Java 10 General Availability
- Изменения в стандартной библиотеке Java 10
- Записки о миграции на Java 10
- Как Java 10 изменяет способ использования анонимных внутренних классов
- "Жизнь после Java 10": какие изменения принесет Java 11
- 90 новых фич (и API) в JDK 11
- Java 11: новое в String
- Java 11 / JDK 11: General Availability
- 39 новых фич, которые будут доступны в Java 12
- Пришло время Java 12! Обзор горячих JEP-ов
- Новое в Java 12: The Teeing Collector
- Только что вышла Java 13
- В Java 13 хотят добавить "текстовые блоки"
- Introducing Java 13: Let's dive Into JDK's New Features
- Что нового будет в Java 14
- Java 14 is coming
- Java 14: Record, более лаконичный instanceof, упаковщик jpackage, switch-лямбды и текстовые блоки
- Исследуем записи в Java 14
- Пробуем улучшенный оператор instanceof в Java 14
- Исследуем sealed классы в Java 15
- Sealed classes. Semantics vs performance
- Sealed типы в Java
- Что нового в Java 15?
- Вышла Java 15
- Project Panama: как сделать Java "ближе к железу"?
- Раздача халявы: нетормозящие треды в Java. Project Loom
- Project Loom: виртуальные потоки в Java уже близко
- Десять вещей, которые можно делать с GraalVM
- Как работает Graal — JIT-компилятор JVM на Java
- Graal: как использовать новый JIT-компилятор JVM в реальной жизни
- Разрабатываем утилиту на GraalVM
- Скрещиваем ужа с ежом: OpenJDK-11 + GraalVM
- JavaScript, Java, какая теперь разница?
- Что под капотом компиляторных оптимизаций GraalVM?
И не только:
- Java-альманах
- State of Loom: часть 1 и часть 2
- GraalVM
Посмотреть:
- Cay Horstmann — Feature evolution in Java 13 and beyond
- Тагир Валеев — Java 9-14: Маленькие оптимизации
- Никита Липский — Java 9 Модули. Почему не OSGi?
- Cay Horstmann — Java 9: the good parts (not modules)
- Владимир Иванов - Project Panama: как сделать Java “ближе к железу”?
- Олег Чирухин — GraalVM Всемогущий
- Олег Чирухин — Graal, Value Types, Loom и прочие ништяки
- Олег Шелаев — Компилируем Java ahead of time с GraalVM
- Олег Шелаев — Суперкомпиляция, partial evaluation, проекции Футамуры и как GraalVM спасет мир
- Project Loom и Новое в JDK 14 на letsCode
- GOTO 2019 • Life After Java 8 • Trisha Gee
- Dalia Abo Sheasha — Migrating beyond Java 8
- Project Loom: Helping Write Concurrent Applications on the Java Platform by Ron Pressler
До Java 9 все строки имели кодировку UTF-16
(2 байта на символ) и хранились в массиве char
.
С Java 9 пришло такое изменение как Compact String. Если все символы строки входят в множество символов Latin-1
(а это подавляющее большинство строк), то каждый из них может поместиться в 1 байт, поэтому в этом случае массив char
избыточен. В результате было принято решение заменить массив char
на массив byte
, что позволяет строкам Latin-1
расходовать меньше памяти. Кодировка строки хранится в отдельном поле byte coder
, значение которого представляет Latin-1
или UTF-16
.
Также интересной особенностью является кеширование классом String
своего hashcode
.
Строки являются неизменяемыми, наследоваться от строк запрещено (final class
). Все операции по изменении строки возвращают её новый экземпляр, в том числе и конкатенация строк. Компилятор умеет оптимизировать конкатенацию и превращать её в объект StringBuilder и совокупность вызовов методов append
. ОДНАКО! В Java 9 вошёл JEP 280: Indify String Concatenation, который изменил эту оптимизацию и пошёл ещё дальше. Теперь вместо StringBuilder
генерируется bytecode для вызова StringConcatFactory через invokedynamic, поэтому стоит расслабиться и чаще выбирать +
.
Ещё можно упомянуть про String pool
- это выделяемое в heap
пространство, которое используется для оптимизации потребления памяти при хранении строк. Благодаря ему одинаковые строковые литералы могут ссылаться на один и тот же объект.
Стоит помнить, что с помощью String.intern() производительности особой не добиться, а можно наоборот пустить всё по миру. Лучше напишите свою реализацию. Подоробнее читайте в статье Алексея Шипилёва - JVM Anatomy Quark #10: String.intern().
Кроме того, equals и методы поиска (например indexOf) оптимизируются JIT компилятором на нативном уровне.
Посмотреть доклады Алексея Шипилёва на тему строк: Катехизис java.lang.String и The Lord of the Strings: Two Scours.
Подробнее:
- String javadoc
- Как обойти строчку?
- Из чего состоит String?
- JDK 9/JEP 280: конкатенация строк никогда больше не будет прежней на Хабре
- Компактные строки в Java 9 на Хабре
- Guide to Java String Pool на Baeldung
- Compact Strings in Java 9
- Владимир Иванов — Глубокое погружение в invokedynamic
- Charles Nutter — Let's Talk About Invokedynamic
- Что там с JEP-303 или изобретаем invokedynamic
Казалось бы:
byte
- 1 байтshort
- 2 байтаint
- 4 байтаlong
- 8 байтchar
- 2 байтаfloat
- 4 байтаdouble
- 8 байт
А размер boolean не упоминается в спецификации вовсе. Однако также спецификация не запрещает использовать для хранения примитива больше памяти - главное, чтобы размер был достаточным для всех значений. Конкретный объём таки зависит от реализации JVM. Не последнюю роль в этом играет выравнивание данных в памяти.
Похожая ситуация и со ссылочными типами - спецификация JVM не требует какой-то определённой структуры для объектов и отдаёт её на откуп реализации. Все тонкости и секреты занимаемой объектами памяти раскрывает Алексей Шипилёв в своей статье Java Objects Inside Out.
Подробнее:
- The Java Virtual Machine Specification
- Какие существуют примитивы?
- Сколько памяти занимает объект?
- Какие существуют примитивы?
- Размер Java объектов на Хабре
- Java Objects Inside Out
- jol
- Как JVM аллоцирует объекты? на Хабре
- Сжатие указателей в Java на Хабре
- Measuring Object Sizes in the JVM на Bealdung
Если вас заинтересовало представление объектов в jvm и их реализация (и вы умеете-могёте читать C++), то можно пойти посмотреть исходники openjdk. Начать, например, отсюда:
Типы ссылок в Java:
Strong reference
- обычная переменная ссылочного типа в Java. Объект такой ссылки очищается GC не раньше, чем станет неиспользуемым (никто нигде на него больше не ссылается).- Слабые ссылки - сборщик мусора тем или иным образом не учитывает связь ссылки и объекта в куче при выявлении объектов, подлежащих удалению. Объект будет удалён даже при наличии слабой ссылки на него:
Soft reference
- мягкая ссылка, экземпляр класса SoftReference. Объект гарантированно будет собран GC до возникновения OutOfMemoryError. Может использоваться для реализации кэшей, увеличивающихся без рискаOutOfMemoryError
для приложения.Weak reference
- слабая ссылка, экземпляр класса WeakReference. Не препятствует утилизации объекта и игнорируется GC при сборке мусора. Может использоваться для хранения некоторой связанной с объектом информации до момента его смерти. Также стоит обратить внимание на WeakHashMap.Phantom reference
- фантомная ссылка, экземпляр класса PhantomReference. Не препятствует утилизации объекта и игнорируется GC при сборке мусора и имеет ряд особенностей, описанных ниже. Может быть применена для получения уведомления, что объект стал неиспользуемым и можно освободить связанные с ним ресурсы (как более надёжный вариант, чемfinalize()
, вызов которого не гарантируется, может проводить сеансы воскрешения и вообще deprecated).
Чтобы достать объект из слабых ссылок, необходимо вызывать метод get()
. Если объект недостижим, то метод вернёт null
. Для фантомных ссылок всегда возвращается null
.
При создании слабой ссылки в конструктор можно, а для PhantomReference
необходимо, передать экземпляр ReferenceQueue - в очереди будет сообщение, когда ссылка протухнет. Для SoftReference
и WeakReference
это будет ДО финализации объекта, а для PhantomReference
ПОСЛЕ. Однако фактическое удаление объекта фантомной ссылки из памяти не производится до момента её очистки.
Подробнее: