Java - ByteBuffer或ArrayList <byte>?

时间:2015-07-16 12:08:24

标签: java arraylist bytebuffer

最近我创建了一个包装器来读取和写入byte数组中的数据。要做到这一点,我一直在使用ArrayList<Byte>,但我想知道这是否是最有效的方法,因为:

  • addAll()无法使用byte数组(即使使用Arrays.asList(),也会返回List<Byte[]>)。为了解决这个问题,我只是在每个循环中循环并添加byte,但我想这会假设很多函数调用,因此它具有性能成本。
  • byte[]获取ArrayList也是如此。我无法从Byte[]投射到byte[],所以我必须使用循环。
  • 我认为存储字节而不是字节会占用更多内存。

我知道ByteArrayInputStreamByteArrayOutputStream可以用于此,但它有一些不便之处:

  • 我想实现以不同的字节顺序读取不同数据类型的方法(例如,readIntreadLEIntreadUInt等),而这些类只能读/写一个字节或一个字节数组。这不是一个真正的问题,因为我可以在包装器中解决这个问题。但这是第二个问题。
  • 我希望能够同时写和读,因为我使用它来解压缩一些文件。因此,要为其创建包装器,我需要同时包含ByteArrayInputStreamByteArrayOutputStream。我不知道那些是否可以以某种方式同步,或者每次我写信给包装器时我都必须将一个数据写入另一个。

所以,我的问题就出现了:使用ByteBuffer会更有效吗?我知道您可以从中获取integersfloats等,甚至可以更改字节顺序。我想知道的是,使用ByteBufferArrayList<Byte>之间是否存在真正的性能变化。

3 个答案:

答案 0 :(得分:3)

绝对 ByteBuffer ByteArrayOutputStream 。在你的情况下,ByteBuffer似乎很好。 检查Javadoc,因为它有很好的方法,对于putInt / getInt等,你可能想设置顺序(那4个字节)

byteBuffer.order(ByteBuffer.LITTLE_ENDIAN);

使用文件,您可以使用getChannel()或变体,然后使用MappedByteBuffer

ByteBuffer可以包装一个字节数组,或者分配。

答案 1 :(得分:1)

请记住,每个对象都有与之相关的开销,包括每个对象的一些内存和一旦超出范围的垃圾回收。

使用List<Byte>意味着每个字节创建/垃圾收集一个对象非常浪费。

答案 2 :(得分:0)

ByteBuffer是一个围绕字节数组的包装类,它不像ArrayList那样具有动态大小,但它每字节消耗的内存更少,速度更快。 如果你知道你需要的大小,那么使用ByteBuffer,如果你没有,那么你可以使用ByteArrayOutputStream(也许可以用ObjectOutputStream包装,它有一些方法来编写不同类型的数据)。要读取你写入ByteArrayOutputStream的数据,你可以扩展ByteArrayOutputStream,然后你可以访问字段buf []和count,这些字段是受保护的,所以你可以从扩展类访问它们,它看起来像:

public class ByteArrayOutputStream extends OutputStream {

    /**
     * The buffer where data is stored.
     */
    protected byte buf[];
    /**
     * The number of valid bytes in the buffer.
     */
    protected int count;
...
}


public class ReadableBAOS extends ByteArrayOutputStream{
    public byte readByte(int index) {
        if (count>index) {
            throw new IndexOutOfBoundsException();
        }
        return buf[index];
    }
}

所以你可以在扩展类中创建一些方法来从底层缓冲区读取一些字节,而不需要每次像toByteArray()方法那样复制它的内容。