«1. Обзор
В этом уроке мы узнаем, как построить список, содержащий примитивные целочисленные значения.
Мы рассмотрим решения, использующие ядро Java и внешние библиотеки.
2. Автоупаковка
В Java аргументы универсального типа должны быть ссылочными типами. Это означает, что мы не можем сделать что-то вроде List\u003cint\u003e.
Вместо этого мы можем использовать List\u003cInteger\u003e и использовать автоупаковку. Автоупаковка помогает нам использовать интерфейс List\u003cInteger\u003e так, как если бы он содержал примитивные значения типа int. Под капотом это по-прежнему набор объектов, а не примитивов.
Основное решение Java — это просто настройка, позволяющая использовать примитивы с универсальными коллекциями. Кроме того, это связано со стоимостью конвертации упаковки и распаковки.
Однако в Java есть другие варианты и дополнительные сторонние библиотеки, которые мы можем использовать. Давайте посмотрим, как их использовать ниже.
3. Использование Stream API
Часто нам не столько нужно создавать список, сколько просто работать с ним.
В этих случаях вместо создания списка можно использовать Stream API Java 8. Класс IntSream предоставляет последовательность примитивных элементов типа int, которая поддерживает последовательные агрегатные операции.
Давайте кратко рассмотрим пример:
IntStream stream = IntStream.of(5, 10, 0, 2, -8);
Статический метод IntStream.of() возвращает последовательный IntStream.
Точно так же мы можем создать IntStream из существующего массива целых чисел:
int[] primitives = {5, 10, 0, 2, -8};
IntStream stream = IntStream.of(primitives);
Кроме того, мы можем применить стандартные операции Stream API для итерации, фильтрации и агрегирования целых чисел. Например, мы можем вычислить среднее значение положительных значений int:
OptionalDouble average = stream.filter(i -> i > 0).average();
Самое главное, что при работе с потоками не используется автобокс.
Хотя, если нам определенно нужен конкретный список, мы захотим взглянуть на одну из следующих сторонних библиотек.
4. Использование Trove
Trove — это высокопроизводительная библиотека, предоставляющая примитивные коллекции для Java.
Чтобы настроить Trove с Maven, нам нужно включить зависимость trov4j в наш pom.xml:
<dependency>
<groupId>net.sf.trove4j</groupId>
<artifactId>trove4j</artifactId>
<version>3.0.2</version>
</dependency>
С помощью Trove мы можем создавать списки, карты и наборы.
Например, существует интерфейс TIntList с его реализацией TIntArrayList для работы со списком значений int:
TIntList tList = new TIntArrayList();
Несмотря на то, что TIntList не может напрямую реализовать List, его методы очень сопоставимы. Другие решения, которые мы обсуждаем, следуют аналогичному шаблону.
Самым большим преимуществом использования TIntArrayList является увеличение производительности и потребления памяти. Никакой дополнительной упаковки/распаковки не требуется, так как данные хранятся внутри массива int[].
5. Использование Fastutil
Другой высокопроизводительной библиотекой для работы с примитивами является Fastutil. Давайте добавим зависимость fastutil:
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.1.0</version>
</dependency>
Теперь мы готовы ее использовать:
IntArrayList list = new IntArrayList();
Конструктор по умолчанию IntArrayList() внутренне создает массив примитивов с емкостью по умолчанию 16. В том же vein, мы можем инициализировать его из существующего массива:
int[] primitives = new int[] {5, 10, 0, 2, -8};
IntArrayList list = new IntArrayList(primitives);
6. Использование Colt
Colt — это высокопроизводительная библиотека с открытым исходным кодом для научных и технических вычислений. Пакет cern.colt содержит списки изменяемого размера, содержащие примитивные типы данных, такие как int.
Во-первых, давайте добавим зависимость colt:
<dependency>
<groupId>colt</groupId>
<artifactId>colt</artifactId>
<version>1.2.0</version>
</dependency>
Список примитивов, который предлагает эту библиотеку, cern.colt.list.IntArrayList:
cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList();
Начальная емкость по умолчанию равна десяти.
7. Использование Guava
Guava предоставляет несколько способов взаимодействия между примитивными массивами и API коллекций. В пакете com.google.common.primitives есть все классы для размещения примитивных типов.
Например, класс ImmutableIntArray позволяет создать неизменяемый список элементов типа int.
Предположим, у нас есть следующий массив значений int:
int[] primitives = new int[] {5, 10, 0, 2};
Мы можем просто создать список с массивом:
ImmutableIntArray list = ImmutableIntArray.builder().addAll(primitives).build();
Кроме того, он предоставляет список API со всеми стандартными методами, которые мы ожидать.
8. Заключение
В этой быстрой статье мы показали несколько способов создания списков с примитивными целыми числами. В наших примерах мы использовали библиотеки Trove, Fastutil, Colt и Guava.
Как обычно, полный код этой статьи доступен на GitHub.