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

时间:2011-10-01 17:49:26

标签: java collections bytearray

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

到目前为止候选人是:

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

这似乎是一个奇怪的遗漏,我确信我必须错过某个地方。我只想弄清楚什么。我错过了什么?

3 个答案:

答案 0 :(得分:3)

我会考虑将一个包含byte[]数组的的类作为ArrayListVector的元素。

使每个块成为例如1024字节,因此访问器函数可以index >> 10访问ArrayList的正确元素,然后访问index & 0x3ff以访问该数组的特定字节元素。

这将避免将每个byte视为Byte对象的浪费,而浪费的是最后一块末尾遗留下来的任何东西。

答案 1 :(得分:1)

在这些情况下,我只是初始化对合理长度数组的引用,当它变得太小时,通过调用Arrays.copyOf()创建并将其复制到更大的数组。 e.g:

byte[] a = new byte[16];
if (condition) {
    a = Arrays.copyOf(a, a.length*2);
}

如果需要的话,我们可以将它包装在一个类中......

答案 2 :(得分:0)

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

为了提高效率,您可以从一个不错的初始容量开始。请参阅构造函数:

ArrayList(int initialCapacity) 

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

尽管看起来如此, ArrayList即使拥有一百万条记录也非常高效!我写了一个小型测试程序,它将一百万条记录添加到一个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());
        }
}

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

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

tot=31522816 free=31023176
Elapsed: 74
tot=31522816 free=22537648