В Java 8 есть класс ByteStream?
Java 8 предоставляет Stream<T>
специальности double
, int
и long
: DoubleStream
, IntStream
и LongStream
соответственно. Однако я не смог найти эквивалента для byte
на документация.
предоставляет ли Java 8 ByteStream
класса?
2 ответов
нет, его не существует. На самом деле он явно не был реализован, чтобы не загромождать API потока тоннами классов для каждого примитивного типа.
цитирую почта от Брайана Гетца в списке рассылки OpenJDK:
короткий ответ: нет.
Это не стоит еще 100K + JDK footprint каждый для этих форм которые используются почти никогда. И если мы добавим их, кто-нибудь спрос короткий, float или логический.
иными словами, если люди настаивали, что у нас есть все примитивные специализации, у нас не было бы примитивных специализаций. Который было бы хуже, чем статус-кво.
большинство операций, связанных с байтами, автоматически повышаются до int. Например, рассмотрим простой метод, который добавляет byte
константы для каждого элемента byte[]
массив возвращает new byte[]
array (потенциальный кандидат на ByteStream
):
public static byte[] add(byte[] arr, byte addend) {
byte[] result = new byte[arr.length];
int i=0;
for(byte b : arr) {
result[i++] = (byte) (b+addend);
}
return result;
}
смотрите, хотя мы выполняем сложение из двух byte
переменные, они расширены до int
и вам нужно вернуть результат в byte
. В Java байт-код большая часть byte
операции (за исключением загрузка/хранение массива и приведение к байту) выражаются 32-разрядными целочисленными инструкциями (iadd
, ixor
, if_icmple
и так далее). Таким образом, практически нормально обрабатывать байты как ints с IntStream
. Нам просто нужны две дополнительные операции:
- создать
IntStream
Сbyte[]
array (расширение байтов до ints) - собрать
IntStream
tobyte[]
массив (используя(byte)
cast)
первый очень прост и может быть реализован как это:
public static IntStream intStream(byte[] array) {
return IntStream.range(0, array.length).map(idx -> array[idx]);
}
таким образом, вы можете добавить такой статический метод в свой проект и быть счастливым.
сбор потока в byte[]
массив-это сложнее. Используя стандартные классы JDK, самым простым решением является ByteArrayOutputStream
:
public static byte[] toByteArray(IntStream stream) {
return stream.collect(ByteArrayOutputStream::new, (baos, i) -> baos.write((byte) i),
(baos1, baos2) -> baos1.write(baos2.toByteArray(), 0, baos2.size()))
.toByteArray();
}
однако он имеет ненужные накладные расходы из-за синхронизации. Также было бы неплохо специально обработать потоки известной длины, чтобы уменьшить выделение и копирование. Тем не менее теперь вы можете использовать Stream API для byte[]
массивы:
public static byte[] addStream(byte[] arr, byte addend) {
return toByteArray(intStream(arr).map(b -> b+addend));
}
мой StreamEx библиотека имеет обе эти операции в IntStreamEx
класс, который расширяет стандартный IntStream
, поэтому вы можете использовать его так:
public static byte[] addStreamEx(byte[] arr, byte addend) {
return IntStreamEx.of(arr).map(b -> b+addend).toByteArray();
}
внутри toByteArray()
метод использует простое изменение размера байт и специально ручками случай, когда поток является последовательным и целевой размер известен заранее.