Java - ByteBuffer 或 ArrayList<Byte>?

Posted

技术标签:

【中文标题】Java - ByteBuffer 或 ArrayList<Byte>?【英文标题】:Java - ByteBuffer or ArrayList<Byte>? 【发布时间】:2015-07-16 12:08:23 【问题描述】:

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

addAll() 不适用于 byte 数组(即使使用 Arrays.asList(),它返回我 List&lt;Byte[]&gt;)。为了解决这个问题,我只是循环并在每个循环中添加一个byte,但我想这会假设有很多函数调用,因此会降低性能。 从ArrayList 获取byte[] 也是如此。我无法从Byte[] 转换为byte[],所以我必须使用循环。 我想存储 Byte 而不是 byte 会占用更多内存。

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

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

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

【问题讨论】:

ArrayList&lt;Byte&gt; 听起来不是个好主意。 如果你需要动态大小的缓冲区,那么看看我的评论,使用 ByteArrayOutputStream,扩展它并利用fileds buf 和count,做一些快速阅读的方法。它具有冒险性,具有动态大小; 【参考方案1】:

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

byteBuffer.order(ByteBuffer.LITTLE_ENDIAN);

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

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

【讨论】:

【参考方案2】:

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

使用List&lt;Byte&gt; 意味着每字节创建/垃圾收集一个对象,这是非常浪费的。

【讨论】:

【参考方案3】:

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() 方法那样每次都复制其内容。

【讨论】:

ByteBuffer 不是byte[] 的包装类,尽管您可以用它包装byte[]。如果您使用allocateDirect,您将获得本机内存而不是byte[]

以上是关于Java - ByteBuffer 或 ArrayList<Byte>?的主要内容,如果未能解决你的问题,请参考以下文章

Java ByteBuffer 到字符串

在 Java 中将 ByteBuffer 转换为字符串

什么是 C# 中 Java 的 ByteBuffer.wrap 的等价物?

将异常的堆栈跟踪转换为 byte[] 数组或 ByteBuffer (Java) 是不是更有效?

Java - ByteBuffer 或 ArrayList<Byte>?

Honeycomb 下的 Android 不支持 Bytebuffer array() 方法