Перейти к основному содержимому

Преобразование между потоком и массивом в Java

· 4 мин. чтения

1. Введение

Обычно требуется преобразовать различные динамические структуры данных в массивы .

В этом руководстве мы покажем, как преобразовать поток в массив и наоборот в Java.

2. Преобразование потока в массив

2.1. Справочник по методу

Лучший способ преобразовать Stream в массив — использовать метод Stream toArray () :

public String[] usingMethodReference(Stream<String> stringStream) {
return stringStream.toArray(String[]::new);
}

Теперь мы можем легко проверить, было ли преобразование успешным:

Stream<String> stringStream = Stream.of("foreach", "convert", "to", "string", "array");
assertArrayEquals(new String[] { "foreach", "convert", "to", "string", "array" },
usingMethodReference(stringStream));

2.2. Лямбда-выражение

Другой эквивалент — передать лямбда-выражение в метод toArray ():

public static String[] usingLambda(Stream<String> stringStream) {
return stringStream.toArray(size -> new String[size]);
}

Это даст нам тот же результат, что и при использовании ссылки на метод.

2.3. Пользовательский класс

Или мы можем сделать все возможное и создать полноценный класс.

Как видно из документации Stream , в качестве аргумента он принимает IntFunction . Он принимает размер массива в качестве входных данных и возвращает массив этого размера.

Конечно, IntFunction — это интерфейс, поэтому мы можем его реализовать:

class MyArrayFunction implements IntFunction<String[]> {
@Override
public String[] apply(int size) {
return new String[size];
}
};

Затем мы можем построить и использовать как обычно:

public String[] usingCustomClass(Stream<String> stringStream) {
return stringStream.toArray(new MyArrayFunction());
}

Следовательно, мы можем сделать то же утверждение, что и ранее.

2.4. Примитивные массивы

В предыдущих разделах мы рассмотрели, как преобразовать поток строк в массив строк. На самом деле мы можем выполнить преобразование таким образом для любого объекта , и это будет очень похоже на приведенные выше примеры String .

Однако для примитивов все немного по-другому. Например, если у нас есть поток целых чисел , который мы хотим преобразовать в int[] , нам сначала нужно вызвать метод mapToInt () :

public int[] intStreamToPrimitiveIntArray(Stream<Integer> integerStream) {
return integerStream.mapToInt(i -> i).toArray();
}

В нашем распоряжении также есть методы mapToLong() и mapToDouble() . Также обратите внимание, что на этот раз мы не передавали никаких аргументов toArray() .

Наконец, давайте сделаем утверждение о равенстве и подтвердим, что мы правильно получили наш массив int :

Stream<Integer> integerStream = IntStream.rangeClosed(1, 7).boxed();
assertArrayEquals(new int[]{1, 2, 3, 4, 5, 6, 7}, intStreamToPrimitiveIntArray(integerStream));

А что, если нам нужно сделать наоборот? Давайте взглянем.

3. Преобразование массива в поток

Мы, конечно, можем пойти и другим путем. И в Java для этого есть специальные методы.

3.1. Массив объектов _

Мы можем преобразовать массив в поток , используя методы Arrays.stream() или Stream.of() :

public Stream<String> stringArrayToStreamUsingArraysStream(String[] stringArray) {
return Arrays.stream(stringArray);
}

public Stream<String> stringArrayToStreamUsingStreamOf(String[] stringArray) {
return Stream.of(stringArray);
}

Следует отметить, что в обоих случаях наш Stream имеет то же время, что и наш массив.

3.2. Массив примитивов

Точно так же мы можем преобразовать массив примитивов:

public IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) {
return Arrays.stream(intArray);
}

public Stream<int[]> primitiveIntArrayToStreamUsingStreamOf(int[] intArray) {
return Stream.of(intArray);
}

Но, в отличие от преобразования массивов Object , есть важное отличие. При преобразовании массива примитивов Arrays.stream() возвращает IntStream , а Stream.of() возвращает Stream<int[]> .

3.3. Arrays.stream против Stream.of

Чтобы понять различия, упомянутые в предыдущих разделах, мы рассмотрим реализацию соответствующих методов.

Давайте сначала взглянем на реализацию этих двух методов в Java:

public <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}

public <T> Stream<T> of(T... values) {
return Arrays.stream(values);
}

Мы видим, что Stream.of() на самом деле вызывает Arrays.stream() внутри, и это, очевидно, причина, по которой мы получаем те же результаты.

Теперь проверим методы в случае, когда мы хотим преобразовать массив примитивов:

public IntStream stream(int[] array) {
return stream(array, 0, array.length);
}

public <T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

На этот раз Stream.of() не вызывает Arrays.stream() .

4. Вывод

В этой статье мы увидели, как мы можем преобразовать Stream в массивы в Java и наоборот. Мы также объяснили, почему мы получаем разные результаты при преобразовании массива Object и при использовании массива примитивов.

Как всегда, полный исходный код можно найти на GitHub .