如何使用Java 8 Stream映射和收集原始返回类型

时间:2017-06-22 20:10:07

标签: java arrays java-8 byte java-stream

我是Java 8流的新手,我想知道是否有办法forEach/map调用方法返回byte并接受int作为参数。

示例:

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[]
   }
}

正如您可能猜到的那样,getBytes方法无效。 "int[] cannot be converted to int"可能某个地方缺少预告,但个人无法弄明白。

然而,这是一种有效的,老式的方法,我想将其重写为Stream。

byte[] byteArray = new byte[indexes.length];
for ( int i = 0; i < byteArray.length; i++ ) {
   byteArray[i] = this.getByte( indexes[i] );
}
return byteArray;

3 个答案:

答案 0 :(得分:5)

如果您愿意使用第三方库,Eclipse Collections对所有八种Java基元类型都有集合支持。以下应该有效:

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

更新:我将原始代码更改为懒惰。

注意:我是Eclipse Collections的提交者

答案 1 :(得分:4)

您可以编写自己的Collector并使用byte[]构建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);
  }
}

并使用它:

public byte[] getBytes(int... indexes) {
  return IntStream.of(indexes).mapToObj(this::getByte).collect(MyCollectors.toByteArray());
}

答案 2 :(得分:3)

用流来做这个没有好办法。使用collect的任何实现都将依赖于附加元素,这对于数组来说非常难看。这就像你要获得的那样接近:

int[] ints = IntStream.of(indexes)
        .map(this::getByte) // upcast to int, still IntStream
        .toArray(); // specialized collect

IntStream.toArray方法有大量的开销涉及内部&#34;节点&#34;对象和数组连接,因此效率也低得多。我建议坚持使用旧的for循环。