我正在尝试找到一个用于在Java中存储字节向量的类,它支持:随机访问(所以我可以在任何地方获取或设置一个字节),调整大小(所以我可以将内容附加到最后或者其他手动更改大小),合理的效率(我可能在这些东西中存储兆字节数据),全部都在内存中(我没有文件系统)。有什么建议吗?
到目前为止候选人是:
byte[]
。不可调整大小。java.util.Vector<Byte>
。邪恶。也很痛苦。java.io.ByteArrayOutputStream
。不是随机访问。java.nio.ByteBuffer
。不可调整大小。org.apache.commons.collections.primitives.ArrayByteList
。不可调整大小。这很奇怪,因为它会自动调整大小,如果你添加东西,你就不能明确地改变大小!java.nio.channels.FileChannel
的纯RAM实现。找不到一个。 (请记住,我没有文件系统。)这似乎是一个奇怪的遗漏,我确信我必须错过某个地方。我只想弄清楚什么。我错过了什么?
答案 0 :(得分:3)
我会考虑将一个包含byte[]
数组的块的类作为ArrayList
或Vector
的元素。
使每个块成为例如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