Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Java 8, is there a ByteStream class?

Java 8 provides Stream<T> specializations for double, int and long: DoubleStream, IntStream and LongStream respectively. However, I could not find an equivalent for byte in the documentation.

Does Java 8 provide a ByteStream class?

like image 359
sdgfsdh Avatar asked Sep 08 '15 13:09

sdgfsdh


People also ask

Which are byte stream classes in java?

The ByteStream classes are divided into two types of classes, i.e., InputStream and OutputStream. These classes are abstract and the super classes of all the Input/Output stream classes.

What are the stream classes in java?

There are two basic types of stream defined by Java, called byte stream and character stream. The byte stream classes provide a convenient means for handling input and output of bytes and character streams provide a convenient means for handling input and output of characters, respectively.

What are streams in java 8?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.

What is the byte stream in java?

Byte Streams Java byte streams are used to perform input and output of 8-bit bytes. Though there are many classes related to byte streams but the most frequently used classes are, FileInputStream and FileOutputStream.


2 Answers

No, it does not exist. Actually, it was explicitly not implemented so as not to clutter the Stream API with tons of classes for every primitive type.

Quoting a mail from Brian Goetz in the OpenJDK mailing list:  

Short answer: no.

It is not worth another 100K+ of JDK footprint each for these forms which are used almost never. And if we added those, someone would demand short, float, or boolean.

Put another way, if people insisted we had all the primitive specializations, we would have no primitive specializations. Which would be worse than the status quo.

like image 170
Tunaki Avatar answered Sep 24 '22 17:09

Tunaki


Most of the byte-related operations are automatically promoted to int. For example, let's consider the simple method which adds a byte constant to each element of byte[] array returning new byte[] array (potential candidate for 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; } 

See, even though we perform an addition of two byte variables, they are widened to int and you need to cast the result back to byte. In Java bytecode most of byte-related operations (except array load/store and cast to byte) are expressed with 32-bit integer instructions (iadd, ixor, if_icmple and so on). Thus practically it's ok to process bytes as ints with IntStream. We just need two additional operations:

  • Create an IntStream from byte[] array (widening bytes to ints)
  • Collect an IntStream to byte[] array (using (byte) cast)

The first one is really easy and can be implemented like this:

public static IntStream intStream(byte[] array) {     return IntStream.range(0, array.length).map(idx -> array[idx]); } 

So you may add such static method to your project and be happy.

Collecting the stream into byte[] array is more tricky. Using standard JDK classes the simplest solution is 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(); } 

However it has unnecessary overhead due to synchronization. Also it would be nice to specially process the streams of known length to reduce the allocations and copying. Nevertheless now you can use the Stream API for byte[] arrays:

public static byte[] addStream(byte[] arr, byte addend) {     return toByteArray(intStream(arr).map(b -> b+addend)); } 

My StreamEx library has both of these operations in the IntStreamEx class which enhances standard IntStream, so you can use it like this:

public static byte[] addStreamEx(byte[] arr, byte addend) {     return IntStreamEx.of(arr).map(b -> b+addend).toByteArray(); } 

Internally toByteArray() method uses simple resizable byte buffer and specially handles the case when the stream is sequential and target size is known in advance.

like image 23
Tagir Valeev Avatar answered Sep 24 '22 17:09

Tagir Valeev