与"Byte array of unknown length in java"类似,我需要能够将数据源中未知数量的字节写入byte []数组。 然而我需要能够从先前存储的字节读取压缩算法,因此ByteArrayOutputStream对我不起作用。
现在我有一个方案,我分配固定大小N的ByteBuffers,添加一个新的,当我达到N,2N,3N字节等。数据耗尽后我将所有缓冲区转储到一个现在已知大小的数组
有更好的方法吗?固定大小的缓冲区降低了压缩算法的灵活性。
答案 0 :(得分:5)
使用循环字节缓冲区怎么样?它有可能动态增长并且效率很高。
这里有一个实现:http://ostermiller.org/utils/CircularByteBuffer.java.html
答案 1 :(得分:4)
为什么不将ByteArrayOutputStream
作为子类?这样,您的子类可以访问受保护的buf
和count
字段,您可以向类添加方法以直接操作它们。
答案 2 :(得分:2)
ByteArrayOutputStream的费用是调整底层数组的大小。你的固定块程序消除了很多。如果调整大小对你来说不够昂贵(例如在测试中ByteArrayOutputStream“足够快”,并且不提供撤消内存压力),那么根据vanza建议的子类化ByteArrayOutputStream可能对你有用。
我不知道你的压缩算法,所以我不能说为什么你的块列表使它不那么灵活,甚至为什么压缩算法甚至不知道块。但由于块可以通过动态,您可以适当调整块大小,以更好地支持您正在使用的各种压缩算法。
如果压缩算法可以在“流”上工作(即固定大小的数据块),则块大小应该很重要,因为您可以隐藏实现中的所有这些细节。完美的世界是,如果压缩算法希望其数据块与您分配的块的大小相匹配,那么您就不必复制数据来为压缩器提供数据。
答案 3 :(得分:2)
虽然你当然可以使用ArrayList,你几乎可以看到4-8倍的内存开销 - 假设字节不是新分配但是共享一个全局实例(因为这对于整数是真的,我认为它有效对于字节也是如此) - 并且你丢失了所有缓存局部性。
因此,虽然您可以将ByteArrayOutputStream子类化,但即使在那里您也不需要开销(方法已同步)。所以我个人会推出自己的类,当你写它时它会动态增长。效率低于您当前的方法,但很简单,我们都知道具有摊销成本的部分 - 否则您显然也可以使用您的解决方案。只要您将解决方案包装在一个干净的界面中,您就会隐藏复杂性并仍能获得良好的性能
或以其他方式说:不,你几乎不能比你已经做的更有效率,并且每个内置的java Collection都应该因为某种原因而表现更差。
答案 4 :(得分:2)
克里斯回答说CircularByteBuffer api是要走的路。幸运的是,它现在在中央maven repo。引用this link的摘录,简单如下:
// buffer all data in a circular buffer of infinite size
CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
class1.putDataOnOutputStream(cbb.getOutputStream());
class2.processDataFromInputStream(cbb.getInputStream());
最后,我们没有内存问题和管道API
答案 5 :(得分:0)
为简单起见,您可以考虑使用java.util.ArrayList
:
ArrayList<Byte> a = new ArrayList<Byte>();
a.add(value1);
a.add(value2);
...
byte value = a.get(0);
Java 1.5及更高版本将在byte
和Byte
类型之间提供自动装箱和拆箱功能。性能可能略微比ByteArrayOutputStream
更差,但它易于阅读和理解。