3

I have a byte[] and I want to make a byte stream.

For int[] and long and double, I see methods in the Arrays class:

Arrays.stream(int[] array)
Arrays.stream(long[] array)
Arrays.stream(double[] array)

However, I don't see any for a method Arrays.stream(byte[] array).

What then is the easiest and most concise way to then get a stream of byte primitives as actual bytes?

I need to do transformations on byte[]'s and I need a Stream of bytes to do it using all the Stream functions (and no, I don't want to convert them all to ints.)

Who has a nice solution?

PS. Someone else is providing me the byte[] from a microcontroller API ... So I don't want to play with some other data type if not necessary.

Thanks.

The Coordinator
  • 12,607
  • 11
  • 41
  • 71
  • What's wrong with boxing the bytes to a `Stream`? The boxing [is cached](https://docs.oracle.com/javase/8/docs/api/java/lang/Byte.html#valueOf-byte-), so it doesn't cost you anything more than an index lookup. Then you can work with the Bytes using all of the Stream stuff, and Java will auto-unbox and re-box them as needed for you. – yshavit Nov 23 '19 at 02:25
  • @yshavit That's fine. But it requires an intermediate step to create another array and then move the `byte` to a `Byte`. Why not post and answer? Let's see your full solution. – The Coordinator Nov 23 '19 at 02:29
  • 1
    I don't think this is a dupe of [this question](https://stackoverflow.com/questions/32459683/in-java-8-is-there-a-bytestream-class). That question has a narrow scope: yes or no, does a ByteStream exist. This question asks what can be done about it. – yshavit Nov 23 '19 at 02:37
  • 2
    @yshavit I agree. I'm glad it was reopened. – WJS Nov 23 '19 at 02:58
  • Depending on what you want to do with the stream, you could use the old `new DataInputStream(new ByteArrayInputStream(bytes));` instead – boot-and-bonnet Nov 23 '19 at 04:47
  • I need to do Stream operations. The InputStream types do not offer a Stream conversion. – The Coordinator Nov 23 '19 at 07:14

3 Answers3

4

A Stream<Byte> is about as good as a ByteStream of primitives would be, since Byte#valueOf returns cached instances of the boxed values (and the compiler handles boxing and unboxing for you). So then the only trick is to turn your byte[] into a Stream<Byte>.

One way to do that would be to create an IntStream of indexes, and then map those indexes into lookups into your byte[]:

byte[] byteArray = "hello".getBytes();
Stream<Byte> byteStream = IntStream.range(0, byteArray.length)
    .mapToObj(i -> byteArray[i]);

I don't know of any helper method in the JDK that does this for you.

yshavit
  • 41,077
  • 7
  • 83
  • 120
2

You could do something like this.

      byte[] a = { 1, 2, 3, 4
      };

      byteStream(a).forEach(System.out::println);


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

      public static byte[] toByteArray(IntStream b) {
        Byte[] barray = b.map(a->a&0xFF).boxed().toArray(Byte[]::new);
        byte[] ret = new byte[barray.length];
        System.arraycopy(barray,0,ret,0,barray.length);
        return ret;
      }

Otherwise you may need to use Steam with Byte since the primitive implementations of byte, float, and short don't exist. I believe Guava supports byte streams.

WJS
  • 30,162
  • 4
  • 20
  • 36
  • `IntStream.range(0, a.length).map(idx -> a[idx]);` I like that. It isn't too complicated either! – The Coordinator Nov 23 '19 at 02:32
  • 1
    @TheCoordinator But fair warning. It has it's limitations. It is still an Intstream and there is no easy way to get it back into a primitive byte array. – WJS Nov 23 '19 at 02:35
0

You can do it like this

byte[] byteArray = "Hello World".getBytes();

    Stream.Builder<Byte> builder = Stream.builder();
    for (int i = 0; i < byteArray.length; i++) {
        builder.add(byteArray[i]);
    }
    Stream<Byte> stream = builder.build();

    stream.forEach(str -> System.out.print(str + " ")); 

    /*for(Object b : stream.toArray()){
        String a= new String(new byte[]{(byte)b});
        System.out.println(a);
    }*/