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 .