项目列表属性中只有一个字节[],

时间:2019-11-29 11:13:44

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

我有一个类别为SomeObject的列表

List<SomeObject> list = //fill list;

我只需要一个数组,其列表的所有项目的属性为bytes,且总数为chunk

byte[] allBytes->包含list.get(0).getChunk(), ..,list.get(list.size() - 1).getChunk();

public class BuildArrayBytes {

  public static void main(String[] args) {
    List<SomeObject> list = new ArrayList<>();
    //fill list;
    byte[] allBytes = buildArray(list);
  }

  public static byte[] buildArray(List<SomeObject> list) {
    int totalSize = list.stream()
        .map(item -> item.getChunk())
        .collect(Collectors.summingInt(chunk -> chunk.length));
    byte[] allBytes = new byte[totalSize];

    int position = 0;
    for (int i = 0; i < list.size(); i++) {
      byte[] bytes = list.get(i).getChunk();
      System.arraycopy(bytes, 0, allBytes, position, bytes.length);
      position += bytes.length;
    }
    return allBytes;
  }

  class SomeObject {

    private byte[] chunk;

    public SomeObject(byte[] chunk) {
      this.chunk = chunk;
    }

    public byte[] getChunk() {
      return chunk;
    }

  }
}

使用ByteArrayOutputStream

  public static byte[] buildArray(List<SomeObject> list) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    list.stream().forEach(item -> {
      try {
        byteArrayOutputStream.write(item.getChunk());
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    });
    return byteArrayOutputStream.toByteArray();
  }

它似乎仍然不雅:(

是否可以使用Lambda替换buildArray方法?

1 个答案:

答案 0 :(得分:1)

如果您使用list.stream().forEach(),请考虑使用list.forEach()。如果list.forEach()看起来很糟,请考虑使用普通的for循环,该循环适用于这种带有副作用的处理(例如ByteArrayOutputStream::write)。

如果您坚持使用Stream API的方式(不要与“ lambda”混淆,后者是匿名类实现的一个表达式和快捷方式),请执行以下操作:

list.stream()
    .map(SomeObject::getChunk)
    .forEach(byteArrayOutputStream::write);

由于ByteArrayOutputStream本身不会引发异常,因此SomeObject::getChunk会引发异常。因此,要么在流中处理它(不好):

list.stream()
    .map(i -> try { return i.getChunk(); } 
         catch (IOException ex) { /* handle the exception */ })
    .forEach(byteArrayOutputStream::write);

或在将异常传递到流之前对其进行处理:

list.stream()
    .map(BuildArrayBytes.safeChunk())
    .filter(Objects::nonNull)               // Be careful! Filter out invalid (null) chunks
    .forEach(byteArrayOutputStream::write);

...

private static Function<SomeObject, Integer> safeChunk() {
    return i -> {
        try {
            return i.getChunk();
        } catch (IOException e) {
            /* handle properly */
        }
        return null;
    };
}