3

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.

3
  • You can't make a List of primitives. Look up Arrays.stream and primitive streams. Commented Mar 17, 2017 at 22:02
  • @user2357112 there is no byte stream. Commented Mar 17, 2017 at 22:02
  • @ThorbjørnRavnAndersen: Yup, so you'd need an IntStream. Commented Mar 17, 2017 at 22:05

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

7 Comments

It's not an oversight; it's deliberate. They didn't want a combinatorial explosion of stream classes and methods to deal with different mixtures of primitive types. The stream types they picked were deemed sufficient.
Sure, I know why they did it, and you won't hear me whining about missing short, char or float, but leaving byte out in the cold is unfortunate. It is the primitive type in a way, since you can overlay everything else on an array of byte if you choose, and all the basic stream classes like InputStream operate on streams of bytes. I have frequently missed not having byte stream operations exactly because files, sockets, etc all deal on array of bytes. If I could choose only two, I'd have chosen long and byte.
... of course, most people want int most of all, so I know that wouldn't really work. The combinatorial explosion thing is really a shame, it's a consequence of how Java handles primitives, but it would have been nice if they found a more elegant way around it, or at least provided wrappers for byte[] so that they could be exposed as IntStream but have efficient underlying operations. In any case, I tempered my language to "unfortunate omission" rather than "serious oversight" which seems more accurate. @user2357112
@BeeOnRope thanks for the good information about streams and bytes! Thanks also for the (what are to me) very funny end comments, given you don't know what actual restrictions I am working under, for who, or even why. :)
Well the last comment is more an indication being "pure Java 8" isn't really well-defined? Does it mean using only language features introduced in Java 8? Certainly the Integer and Byte classes have existed since Java 1.x or whatever so that rules out pretty much everything. So the restriction seems ill-formed and arbitrary. Unlike many people who constantly challenge restrictions, I could care less who you work for or why you have this restriction, but the restriction itself should be made clear. @user9999999
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.