Java - ByteBuffer 还是 ArrayList<Byte>?
Java - ByteBuffer or ArrayList<Byte>?
最近我创建了一个包装器来将数据读写到 byte
数组中。为此,我一直在使用 ArrayList<Byte>
,但我想知道这是否是最有效的方法,因为:
addAll()
不适用于 byte
数组(即使使用 Arrays.asList()
,returns 我 List<Byte[]>
)。为了修复它,我只是循环并在每个循环中添加一个 byte
,但我想这假设有很多函数调用,因此它有性能成本。
- 从
ArrayList
获取 byte[]
也是如此。我无法从 Byte[]
转换为 byte[]
,所以我必须为此使用一个循环。
- 我想存储字节而不是字节会占用更多内存。
我知道 ByteArrayInputStream
和 ByteArrayOutputStream
可以用于此,但它有一些不便之处:
- 我想实现以不同字节顺序读取不同数据类型的方法(例如,
readInt
、readLEInt
、readUInt
等),而那些 类 只能读/写一个字节或一个字节数组。这不是真正的问题,因为我可以在包装器中修复它。但是第二个问题来了。
- 我希望能够同时写入和读取,因为我正在使用它来解压缩一些文件。因此,要为它创建一个包装器,我需要同时包含
ByteArrayInputStream
和 ByteArrayOutputStream
。我不知道这些是否可以通过某种方式同步,或者我每次写入包装器时都必须将一个的全部数据写入另一个。
因此,我的问题来了:使用 ByteBuffer
会更有效率吗?我知道您可以从中获取 integers
、floats
等,甚至可以更改字节顺序。我想知道的是,使用 ByteBuffer
和 ArrayList<Byte>
.
之间是否存在真正的性能变化
肯定是ByteBuffer或ByteArrayOutputStream。在你的情况下 ByteBuffer 似乎没问题。 检查 Javadoc,因为它有很好的方法, 对于 putInt/getInt 等,您可能需要设置顺序(这 4 个字节)
byteBuffer.order(ByteBuffer.LITTLE_ENDIAN);
对于文件,您可以使用 getChannel()
或变体,然后使用 MappedByteBuffer
。
一个 ByteBuffer 可以包装一个字节数组,或者分配。
请记住,每个对象都有与之相关的开销,包括每个对象的一点内存和超出范围后的垃圾回收。
使用 List<Byte>
意味着创建/垃圾收集每个字节的对象,这是非常浪费的。
ByteBuffer 是一个字节数组的包装器 class,它不像 ArrayList 那样具有动态大小,但它每字节消耗的内存更少并且速度更快。
如果你知道你需要的大小,那么使用 ByteBuffer,如果你不知道,那么你可以使用 ByteArrayOutputStream(并且可能被 ObjectOutputStream 包装,它有一些方法来写入不同类型的数据)。要读取您写入 ByteArrayOutputStream 的数据,您可以扩展 ByteArrayOutputStream,然后您可以访问字段 buf[] 和 count,这些字段是受保护的,因此您可以通过扩展 class 来访问它们,它看起来像:
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];
}
}
因此您可以在扩展 class 中创建一些方法来从底层缓冲区读取一些字节,而无需像 toByteArray() 方法那样每次都复制其内容。
最近我创建了一个包装器来将数据读写到 byte
数组中。为此,我一直在使用 ArrayList<Byte>
,但我想知道这是否是最有效的方法,因为:
addAll()
不适用于byte
数组(即使使用Arrays.asList()
,returns 我List<Byte[]>
)。为了修复它,我只是循环并在每个循环中添加一个byte
,但我想这假设有很多函数调用,因此它有性能成本。- 从
ArrayList
获取byte[]
也是如此。我无法从Byte[]
转换为byte[]
,所以我必须为此使用一个循环。 - 我想存储字节而不是字节会占用更多内存。
我知道 ByteArrayInputStream
和 ByteArrayOutputStream
可以用于此,但它有一些不便之处:
- 我想实现以不同字节顺序读取不同数据类型的方法(例如,
readInt
、readLEInt
、readUInt
等),而那些 类 只能读/写一个字节或一个字节数组。这不是真正的问题,因为我可以在包装器中修复它。但是第二个问题来了。 - 我希望能够同时写入和读取,因为我正在使用它来解压缩一些文件。因此,要为它创建一个包装器,我需要同时包含
ByteArrayInputStream
和ByteArrayOutputStream
。我不知道这些是否可以通过某种方式同步,或者我每次写入包装器时都必须将一个的全部数据写入另一个。
因此,我的问题来了:使用 ByteBuffer
会更有效率吗?我知道您可以从中获取 integers
、floats
等,甚至可以更改字节顺序。我想知道的是,使用 ByteBuffer
和 ArrayList<Byte>
.
肯定是ByteBuffer或ByteArrayOutputStream。在你的情况下 ByteBuffer 似乎没问题。 检查 Javadoc,因为它有很好的方法, 对于 putInt/getInt 等,您可能需要设置顺序(这 4 个字节)
byteBuffer.order(ByteBuffer.LITTLE_ENDIAN);
对于文件,您可以使用 getChannel()
或变体,然后使用 MappedByteBuffer
。
一个 ByteBuffer 可以包装一个字节数组,或者分配。
请记住,每个对象都有与之相关的开销,包括每个对象的一点内存和超出范围后的垃圾回收。
使用 List<Byte>
意味着创建/垃圾收集每个字节的对象,这是非常浪费的。
ByteBuffer 是一个字节数组的包装器 class,它不像 ArrayList 那样具有动态大小,但它每字节消耗的内存更少并且速度更快。 如果你知道你需要的大小,那么使用 ByteBuffer,如果你不知道,那么你可以使用 ByteArrayOutputStream(并且可能被 ObjectOutputStream 包装,它有一些方法来写入不同类型的数据)。要读取您写入 ByteArrayOutputStream 的数据,您可以扩展 ByteArrayOutputStream,然后您可以访问字段 buf[] 和 count,这些字段是受保护的,因此您可以通过扩展 class 来访问它们,它看起来像:
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];
}
}
因此您可以在扩展 class 中创建一些方法来从底层缓冲区读取一些字节,而无需像 toByteArray() 方法那样每次都复制其内容。