对比FastByteArrayOutputStream与ByteArrayOutputStream的区别

ByteArrayOutputStream


1、基本数据结构:protected byte buf[]; 一维结构

2、write方法:写数组,改变count

1
2
3
4
5
6
7
8
9
10
11
public synchronized void write(byte b[], int off, int len) {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) - b.length > 0)) {
throw new IndexOutOfBoundsException();
}
// 判断是否需要扩容
ensureCapacity(count + len);
// 写数据
System.arraycopy(b, off, buf, count, len);
count += len;
}

  

3、静态扩容(每一次创建一个新数组 byte[]):

1
2
3
4
5
6
7
8
9
10
11
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = buf.length;
int newCapacity = oldCapacity << 1;
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 创建一个新数组。
buf = Arrays.copyOf(buf, newCapacity);
}

 

FastByteArrayOutputStream

1、基本数据结构:private final Deque<byte[]> buffers;

一个存放 byte[] 的deque,二维结构

2、write方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public void write(byte[] data, int offset, int length) throws IOException {
if (offset >= 0 && offset + length <= data.length && length >= 0) {
if (this.closed) {
throw new IOException("Stream closed");
} else {
if (this.buffers.peekLast() == null || ((byte[])this.buffers.getLast()).length == this.index) {
// 如果 deque中最后一个byte[]不存在,或者已经满了,则 新增一个byte[],放到deque尾部
this.addBuffer(length);
}
 
if (this.index + length > ((byte[])this.buffers.getLast()).length) {
int pos = offset;
// 循环创建、循环写数据
do {
if (this.index == ((byte[])this.buffers.getLast()).length) {
// 如果已经满了,就新增一个,放到deque尾部
this.addBuffer(length);
}
 
int copyLength = ((byte[])this.buffers.getLast()).length - this.index;
if (length < copyLength) {
copyLength = length;
}
// 写数据,到deque尾部的byte[]中
System.arraycopy(data, pos, this.buffers.getLast(), this.index, copyLength);
pos += copyLength;
this.index += copyLength;
length -= copyLength;
} while(length > 0);
} else {
System.arraycopy(data, offset, this.buffers.getLast(), this.index, length);
this.index += length;
}
 
}
} else {
throw new IndexOutOfBoundsException();
}
}


1. 找到deque中最后一个 byte数组,写数据到这个数组中
2. 如果这个 数组写不下了,就再创建一个 byte[]数组,放到deque尾部,继续写 (动态扩容,每次只新增一小部分)。

结论:

1、FastByteArrayOutputStream的基础数据结构,相比于ByteArrayOutPutStream的一维数组,它用了一个 二维的数据结构来存放数据。

2、当数据满了需要扩容时,ByteArrayOutPutStream只能重新创建一个容量更大的byte[],来替换之前的,并且复制数据到新byte[]中

3、而FastByteArrayOutputStream,只需要在deque中,再创建一个byte[],直接写数据,写满了,再建一个,放在deque最后。
之前的数据不需要改动,不需要大量的复制操作。

posted @   daibiao123  阅读(1384)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示