什么是Java中可调整大小,随机访问,高效的字节向量类?

Dav*_*ven 5 java collections bytearray

我正在尝试在Java中找到一个用于存储字节向量的类,它支持:随机访问(所以我可以在任何地方获取或设置一个字节),调整大小(所以我可以将内容附加到最后,或者手动更改大小),合理的效率(我可能在这些东西中存储兆字节的数据),都在内存中(我没有文件系统).有什么建议?

到目前为止候选人是:

  • byte[].不可调整大小.
  • java.util.Vector<Byte>.邪恶.也痛苦无效.
  • java.io.ByteArrayOutputStream.不是随机访问.
  • java.nio.ByteBuffer.不可调整大小.
  • org.apache.commons.collections.primitives.ArrayByteList.不可调整大小.这很奇怪,因为它会自动调整大小,如果你添加东西,你就不能明确地改变大小!
  • 纯RAM的实现java.nio.channels.FileChannel.找不到一个.(记住我没有文件系统.)
  • Apache Commons VFS和RAM文件系统.如果我必须,但我真的喜欢更重的东西......

这似乎是一个奇怪的遗漏,我相信我肯定错过了某个地方.我只想弄清楚什么.我错过了什么?

sti*_*vlo 0

ArrayList比 Vector 更高效,因为它不是同步的。

为了提高效率,您可以从适当的初始容量开始。查看构造函数:

ArrayList(int initialCapacity) 
Run Code Online (Sandbox Code Playgroud)

我认为默认值只有 16,而您可能需要更大的尺寸。

不管看起来如何,ArrayList 即使有 100 万条记录也非常高效!我编写了一个小型测试程序,向 ArrayList 添加一百万条记录,没有声明初始容量,在我的 Linux、5 年旧笔记本电脑(Core 2 T5200 cpu)上,只需要大约 100 毫秒即可填满整个列表。如果我声明 100 万字节的初始空间,则需要大约 60-80 毫秒,但如果我声明 10,000 个项目,则可能需要大约 130-160 毫秒,所以最好不要声明任何内容,除非您可以很好地猜测空间需要。

关于内存使用的问题,它需要大约 8 Mb 的内存,我认为这是完全合理的,除非你正在编写手机软件。

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.obliquid.util.StopWatch;

public class ArrayListTest {

        public static void main(String args[]) {
                System.out.println("tot=" + Runtime.getRuntime().totalMemory() 
                     + " free=" + Runtime.getRuntime().freeMemory());
                StopWatch watch = new StopWatch();
                List<Byte> bytes = new ArrayList<Byte>();
                for (int i = 0; i < 1000000; i++) {
                        bytes.add((byte) (i % 256 - 128));
                }
                System.out.println("Elapsed: " 
                     + watch.computeElapsedMillisSeconds());
                System.out.println("tot=" + Runtime.getRuntime().totalMemory() 
                     + " free=" + Runtime.getRuntime().freeMemory());
        }
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,Vector 在 160-200ms 的范围内表现稍差。

示例输出,未指定起始大小并使用 ArrayList 实现。

tot=31522816 free=31023176
Elapsed: 74
tot=31522816 free=22537648
Run Code Online (Sandbox Code Playgroud)

  • 因为它是通用的,所以它会将字节装箱吗?如果是这样,可能会导致巨大的空间效率低下。在最坏的情况下,引用为 1 个字节,而 4 个字节 + 对象头的 8 个字节(OpenJDK 文档说它是两个字)+ 实际字节值的 1 = 13 倍内存消耗。在实践中,字节可能会被填充到 4 个字节,并且“Byte”对象可能会被缓存(快速计算表明缓存所有这些对象只需要 2.2 kB,所以这是完全合理的),因此实际影响取决于并且应该被衡量。 (3认同)