Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map and collect primitive return type using Java 8 Stream

I am new in Java 8 streams and I am wondering if there is way to perform forEach/map call on method returning a byte and accepting an int as parameter.

Example:

public class Test {
   private byte[] byteArray; // example of byte array

   public byte getByte(int index) {
      return this.byteArray[index];
   }

   public byte[] getBytes(int... indexes) {
      return Stream.of(indexes)
             .map(this::getByte) // should return byte
             .collect(byte[]::new); // should return byte[]
   }
}

As you may guess, the getBytes method not working. "int[] cannot be converted to int"Probably somewhere is missing foreach, but personally cant figure it out.

However, this is working, old-fashioned approach which I would like to rewrite as Stream.

byte[] byteArray = new byte[indexes.length];
for ( int i = 0; i < byteArray.length; i++ ) {
   byteArray[i] = this.getByte( indexes[i] );
}
return byteArray;
like image 714
glf4k Avatar asked Jun 22 '17 20:06

glf4k


2 Answers

You can write your own Collector and build your byte[] with an ByteArrayOutputStream:

final class MyCollectors {

  private MyCollectors() {}

  public static Collector<Byte, ?, byte[]> toByteArray() {
    return Collector.of(ByteArrayOutputStream::new, ByteArrayOutputStream::write, (baos1, baos2) -> {
      try {
        baos2.writeTo(baos1);
        return baos1;
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
    }, ByteArrayOutputStream::toByteArray);
  }
}

And use it:

public byte[] getBytes(int... indexes) {
  return IntStream.of(indexes).mapToObj(this::getByte).collect(MyCollectors.toByteArray());
}
like image 184
Flown Avatar answered Oct 01 '22 19:10

Flown


If you are open to using a third-party library, Eclipse Collections has collections support for all eight Java primitive types. The following should work:

public byte[] getBytes(int... indexes) {
    return IntLists.mutable.with(indexes)
            .asLazy()
            .collectByte(this::getByte)
            .toArray();
}

Updated: I changed the original code to be lazy.

Note: I am a committer for Eclipse Collections

like image 31
Donald Raab Avatar answered Oct 01 '22 21:10

Donald Raab