Java - ByteBuffer 或 ArrayList<Byte>?
Posted
技术标签:
【中文标题】Java - ByteBuffer 或 ArrayList<Byte>?【英文标题】:Java - ByteBuffer or ArrayList<Byte>? 【发布时间】:2015-07-16 12:08:23 【问题描述】:最近我创建了一个包装器来读取和写入数据到byte
数组中。为此,我一直在使用ArrayList<Byte>
,但我想知道这是否是最有效的方法,因为:
addAll()
不适用于 byte
数组(即使使用 Arrays.asList()
,它返回我 List<Byte[]>
)。为了解决这个问题,我只是循环并在每个循环中添加一个byte
,但我想这会假设有很多函数调用,因此会降低性能。
从ArrayList
获取byte[]
也是如此。我无法从Byte[]
转换为byte[]
,所以我必须使用循环。
我想存储 Byte 而不是 byte 会占用更多内存。
我知道ByteArrayInputStream
和ByteArrayOutputStream
可以用于此,但它有一些不便:
readInt
、readLEInt
、readUInt
等),而这些类只能读取/写入字节或字节数组.这不是一个真正的问题,因为我可以在包装器中修复它。但是第二个问题来了。
我希望能够同时读写,因为我正在使用它来解压缩一些文件。所以要为它创建一个包装器,我需要同时包含ByteArrayInputStream
和ByteArrayOutputStream
。我不知道这些是否可以以某种方式同步,或者我每次写入包装器时都必须将一个的全部数据写入另一个。
所以,我的问题来了:使用ByteBuffer
会更有效吗?我知道您可以从中获取integers
、floats
等,甚至可以更改字节顺序。我想知道的是,使用 ByteBuffer
和 ArrayList<Byte>
之间是否存在真正的性能变化。
【问题讨论】:
ArrayList<Byte>
听起来不是个好主意。
如果你需要动态大小的缓冲区,那么看看我的评论,使用 ByteArrayOutputStream,扩展它并利用fileds buf 和count,做一些快速阅读的方法。它具有冒险性,具有动态大小;
【参考方案1】:
绝对是 ByteBuffer 或 ByteArrayOutputStream。在您的情况下,ByteBuffer 似乎很好。 检查 Javadoc,因为它有很好的方法, 对于 putInt/getInt 等,您可能需要设置(这 4 个字节的)顺序
byteBuffer.order(ByteBuffer.LITTLE_ENDIAN);
对于文件,您可以使用getChannel()
或变体,然后使用MappedByteBuffer
。
一个 ByteBuffer 可以包装一个字节数组,或者分配。
【讨论】:
【参考方案2】:请记住,每个对象都有与之相关的开销,包括每个对象的一些内存以及超出范围后的垃圾收集。
使用List<Byte>
意味着每字节创建/垃圾收集一个对象,这是非常浪费的。
【讨论】:
【参考方案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>?的主要内容,如果未能解决你的问题,请参考以下文章
什么是 C# 中 Java 的 ByteBuffer.wrap 的等价物?
将异常的堆栈跟踪转换为 byte[] 数组或 ByteBuffer (Java) 是不是更有效?