simpleuser
simpleuser

Reputation: 1682

java 8: how to stream an array of int, extract low bytes, and create an array of byte

To interface two libraries, I need to convert an int[] array holding bytes into a byte[] array of just the low bytes. (I need to mask the ints with 0xFF and store them in a byte[] array.) I can only find examples of how to do that while converting all 4 bytes of the int, which I do not need.

As an exercise I am looking to do this with something short and efficient in pure Java 8 (i.e. valid Java 8 code without external libraries, calls, or SOUP). I tried using streams, but was unable to find a map() that worked; for example:

byte[] mybytarray = Arrays.asList(myintarray).stream().map(v -> v & 0xFF).collect(toList()).toArray(byte[]::new);

but there is the error "Cannot infer type argument(s) for map(Function)" and I do not understand how to write the map.

Upvotes: 3

Views: 1728

Answers (2)

BeeOnRope
BeeOnRope

Reputation: 64925

Unfortunately, steams don't support the byte type directly; i.e,. there is no ByteStream specialization like there are for int and long1.

If you insist on using streams, a reasonably efficient solution is to use a ByteArrayOutputStream to collect the bytes:

ByteArrayOutputStream baos(myintarray.length);
Arrays.stream(myintarray).forEachOrdered(i -> baos.write((byte)i));
byte[] byteArray = baos.toArray();

This only copies the array once. A for loop and explicit array insertion is going to be better still:

byte[] byteArray = new byte[myintarray.length];
for (int i = 0; i < myintarray.length; i++) {
  byteArray[i] = (byte)myintarray[i];
}

Probably slightly more concise than the streams version, and about as fast as you'll get in Java.

If you really insist on a 1-liner with Streams, you can get a Byte[] rather than a byte[] like so:

Arrays.stream(myintarray).boxed().map(Integer::byteValue)
    .collect(Collectors.toList()).toArray(new Byte[myintarray.length]);

This involves a crapload of boxing and you end up with a much larger and slower Byte[], but hey you used a pure Java 8 solution, right?


1 Combinatorial explosion arguments notwithstanding, this has always seemed like an unfortunate omission to me, given the key nature of byte[] in many input/output oriented operations.

Upvotes: 4

Create a byte array with the same size as the int array, and let an index counter run from 0 to the size of the byte array - 1. Get the int value at the index counter and calculate the byte value you need and store it at the same index counter.

Upvotes: 0

Related Questions