Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to convert a byte array to an IntStream?

Java 8 has java.util.stream.Stream and java.util.stream.IntStream types. java.util.Arrays has a method

IntStream is = Arrays.stream(int[])

but no such method to make an IntStream from a byte[], short[] or char[], widening each element to an int. Is there an idiomatic/preferred way to create an IntStream from a byte[], so I can operate on byte arrays in a functional manner?

I can of course trivially convert the byte[] to int[] manually and use Arrays.stream(int[]), or use IntStream.Builder:

public static IntStream stream(byte[] bytes) {
   IntStream.Builder isb = IntStream.builder();
   for (byte b: bytes) 
       isb.add((int) b); 
   return isb.build();
}

but neither is very functional due to the copying of the source.

There also does not seem to be an easy way to convert an InputStream (or in this case an ByteArrayInputStream) to an IntStream, which would be very useful for processing InputStream functionally. (Glaring omission?)

Is there a more functional way that is efficient and does not copy?

like image 974
djb Avatar asked Jan 07 '15 01:01

djb


People also ask

How do you turn an object into a Bytearray?

Write the contents of the object to the output stream using the writeObject() method of the ObjectOutputStream class. Flush the contents to the stream using the flush() method. Finally, convert the contents of the ByteArrayOutputStream to a byte array using the toByteArray() method.

Which process is used for converting byte stream to original structure?

The process of converting a byte array to a String is called decoding.

What is IntStream?

An IntStream interface extends the BaseStream interface in Java 8. It is a sequence of primitive int-value elements and a specialized stream for manipulating int values. We can also use the IntStream interface to iterate the elements of a collection in lambda expressions and method references.


2 Answers

 byte[] bytes = {2, 6, -2, 1, 7};
 IntStream is = IntStream.range(0, bytes.length).map(i -> bytes[i]);

 ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
 IntStream is2 = IntStream.generate(inputStream::read).limit(inputStream.available());
like image 152
Paul Boddington Avatar answered Sep 28 '22 15:09

Paul Boddington


public static IntStream stream(byte[] bytes) {
    ByteBuffer buffer = ByteBuffer.wrap(bytes);
    return IntStream.generate(buffer::get).limit(buffer.remaining());
}

(This can easily be changed to take ints from the ByteBuffer, ie. 4 bytes to the int.)

For InputStream, if you want to consume it eagerly, just read it into a byte[] and use the above. If you want to consume it lazily, you could generate an infinite InputStream using InputStream::read as a Consumer (plus exception handling) and end it when you've reached the end of the stream.

Concerning

but neither is very functional due to the copying of the source

I don't see why that makes it non functional.

Also relevant

  • Why is String.chars() a stream of ints in Java 8?
  • Why are new java.util.Arrays methods in Java 8 not overloaded for all the primitive types?
  • Limit a stream by a predicate
like image 27
Sotirios Delimanolis Avatar answered Sep 28 '22 17:09

Sotirios Delimanolis