Java语言进阶:Buffer类(缓冲区)
Buffer类(缓冲区)
概述:Buffer是一个抽象类,它是对某种基本类型的数组进行了封装。
作用: 在NIO中,就是通过 Buffer 来读写数据的。所有的数据都是用Buffer来处理的,它是NIO读写数据的中转池, 通常使用字节数组。
Buffer主要有如下几种:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
创建ByteBuffer
路径
- 创建ByteBuffer对象的三种方式
讲解
-
ByteBuffer类内部封装了一个byte[]数组,并可以通过一些方法对这个数组进行操作。
-
创建ByteBuffer对象
-
方式一:在堆中创建缓冲区:allocate(int capacity)
public static void main(String[] args) { //创建堆缓冲区 ByteBuffer byteBuffer = ByteBuffer.allocate(10); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XmnmM9iK-1653718194143)(img/17.png)]
-
方式二: 在系统内存创建缓冲区:allocatDirect(int capacity)
public static void main(String[] args) { //创建直接缓冲区 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10); }
-
在堆中创建缓冲区称为:间接缓冲区
-
在系统内存创建缓冲区称为:直接缓冲区
-
间接缓冲区的创建和销毁效率要高于直接缓冲区
-
间接缓冲区的工作效率要低于直接缓冲区
-
-
-
方式三:通过数组创建缓冲区:wrap(byte[] arr)
public static void main(String[] args) { byte[] byteArray = new byte[10]; ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray); }
- 此种方式创建的缓冲区为:间接缓冲区
添加数据-put
讲解
-
public ByteBuffer put(byte b):向当前可用位置添加数据。
-
public ByteBuffer put(byte[] byteArray):向当前可用位置添加一个byte[]数组
-
public ByteBuffer put(byte[] byteArray,int offset,int len):添加一个byte[]数组的一部分
public static void main(String[] args) { yteBuffer b1 = ByteBuffer.allocate(10); // 添加数据 b1.put((byte)11); b1.put((byte)12); b1.put((byte)13); // ByteBuffer转换为普通字节数组 byte[] bytes = b1.array(); System.out.println(Arrays.toString(bytes)); // 打印结果: [11, 12, 13, 0, 0, 0, 0, 0, 0, 0] }
public class Test_添加数据 { public static void main(String[] args) { ByteBuffer b1 = ByteBuffer.allocate(10); // 添加数据 b1.put((byte)11); b1.put((byte)12); b1.put((byte)13); // ByteBuffer转换为普通字节数组 byte[] bytes = b1.array(); System.out.println(Arrays.toString(bytes)); //打印结果: [11, 12, 13, 0, 0, 0, 0, 0, 0, 0] System.out.println("======================="); byte[] b2 = {14,15,16}; // 添加数据 b1.put(b2); // ByteBuffer转换为普通字节数组 byte[] b = b1.array(); System.out.println(Arrays.toString(b)); //打印结果: [11, 12, 13, 14, 15, 16, 0, 0, 0, 0] } }
public class Test_添加数据 { public static void main(String[] args) { ByteBuffer b1 = ByteBuffer.allocate(10); // 添加数据 b1.put((byte)11); b1.put((byte)12); b1.put((byte)13); // ByteBuffer转换为普通字节数组 byte[] bytes = b1.array(); System.out.println(Arrays.toString(bytes)); // 打印结果: [11, 12, 13, 0, 0, 0, 0, 0, 0, 0] System.out.println("======================="); byte[] b2 = {14,15,16}; // 添加数据 b1.put(b2,0,1); // ByteBuffer转换为普通字节数组 byte[] b = b1.array(); System.out.println(Arrays.toString(b)); // 打印结果: [11, 12, 13, 14, 0, 0, 0, 0, 0, 0] } }
容量-capacity
讲解
-
Buffer的容量(capacity)是指:Buffer所能够包含的元素的最大数量。定义了Buffer后,容量是不可变的。
-
示例代码:
public static void main(String[] args) { ByteBuffer b1 = ByteBuffer.allocate(10); System.out.println("容量:" + b1.capacity());//10。之后不可改变 byte[] byteArray = {97, 98, 99, 100}; ByteBuffer b2 = ByteBuffer.wrap(byteArray); System.out.println("容量:" + b2.capacity());//4。之后不可改变 }
-
结果:
容量:10 容量:4
限制-limit
讲解
-
限制limit是指:第一个不应该读取或写入元素的index索引。缓冲区的限制(limit)不能为负,并且不能大于容量。
-
有两个相关方法:
- public int limit():获取此缓冲区的限制。
- public Buffer limit(int newLimit):设置此缓冲区的限制。
-
示例代码:
public class Test_添加数据 { public static void main(String[] args) { ByteBuffer b1 = ByteBuffer.allocate(10); // 添加数据 b1.put((byte)10); // 获取限制 int limit1 = b1.limit(); System.out.println("limit1:"+limit1);// 10 // 设置限制 b1.limit(3); // 添加元素 b1.put((byte)20); b1.put((byte)30); // b1.put((byte)40);// 报异常,因为限制位置索引为3,所以再存14就会报异常:BufferOverflowException } }
位置-position
讲解
-
位置position是指:当前可写入的索引。位置不能小于0,并且不能大于"限制"。
-
有两个相关方法:
- public int position():获取当前可写入位置索引。
- public Buffer position(int p):更改当前可写入位置索引。
-
示例代码:
public class Test_添加数据 { public static void main(String[] args) { ByteBuffer b1 = ByteBuffer.allocate(10); // 添加数据 b1.put((byte)11); // 获取当前位置索引 int position = b1.position(); System.out.println("position:"+position);// 1 // 设置当前位置索引 b1.position(5); b1.put((byte)22); b1.put((byte)33); System.out.println("position:"+b1.position());// 7 System.out.println(Arrays.toString(b1.array())); // 打印结果:[11, 0, 0, 0, 0, 22, 33, 0, 0, 0] } }
小结
-
注意: 字节缓冲数组能操作的范围就是position位置到limit位置:[position,limit)
标记-mark
讲解
-
标记mark是指:当调用缓冲区的reset()方法时,会将缓冲区的position位置重置为该索引。
-
相关方法:
- public Buffer mark():设置此缓冲区的标记为当前的position位置。
- public Buffer reset() : 将此缓冲区的位置重置为以前标记的位置。
-
示例代码:
public static void main(String[] args) { ByteBuffer b1 = ByteBuffer.allocate(10); // 添加数据 b1.put((byte)11); // 获取当前位置索引 int position = b1.position(); System.out.println("position:"+position);// 1 // 标记当前位置索引 b1.mark(); // 添加元素 b1.put((byte)22); b1.put((byte)33); // 获取当前位置索引 System.out.println("position:"+b1.position());// 3 System.out.println(Arrays.toString(b1.array())); // 打印结果:[11, 22, 33, 0, 0, 0, 0, 0, 0, 0] // 重置当前位置索引 b1.reset(); // 获取当前位置索引 System.out.println("position:"+b1.position());// 1 // 添加元素 b1.put((byte)44); System.out.println(Arrays.toString(b1.array())); // 打印结果:[11, 44, 33, 0, 0, 0, 0, 0, 0, 0] }
其它方法
讲解
- public int remaining():获取position与limit之间的元素数。
- public boolean isReadOnly():获取当前缓冲区是否只读。
- public boolean isDirect():获取当前缓冲区是否为直接缓冲区。
- public Buffer rewind():重绕此缓冲区。
- 将position位置设置为:0
- 限制limit不变。
- 丢弃标记。
- public Buffer clear():还原缓冲区的状态。
- 将position设置为:0
- 将限制limit设置为容量capacity;
- 丢弃标记mark。
- public Buffer flip():缩小limit的范围。
- 将limit设置为当前position位置;
- 将当前position位置设置为0;
- 丢弃标记。
package com.itheima.demo11_ByteBuffer常用方法;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* @Author:pengzhilin
* @Date: 2020/9/23 15:33
*/
public class Test6_clear和flip {
public static void main(String[] args) {
/*
- public Buffer clear():还原缓冲区的状态。
- 将限制limit设置为容量capacity;
- 将position设置为:0
- 丢弃标记mark。
- public Buffer flip():缩小limit的范围。
- 将limit设置为当前position位置;
- 将当前position位置设置为0;
- 丢弃标记。
*/
// 创建ByteBuffer字节缓冲数组
ByteBuffer b = ByteBuffer.allocate(10);
// 容量:10,限制:10,位置:0
System.out.println("容量:" + b.capacity() + ",限制:" + b.limit() + ",位置:" + b.position());
// 往b添加数据
b.put((byte) 10);
b.put((byte) 20);
b.put((byte) 30);
// 容量:10,限制:10,位置:3
System.out.println("容量:" + b.capacity() + ",限制:" + b.limit() + ",位置:" + b.position());
System.out.println(Arrays.toString(b.array()));// [10, 20, 30, 0, 0, 0, 0, 0, 0, 0]
/*// 调用clear
b.clear();
// 容量:10,限制:10,位置:0
System.out.println("容量:"+b.capacity()+",限制:"+b.limit()+",位置:"+b.position());
System.out.println(Arrays.toString(b.array()));// [10, 20, 30, 0, 0, 0, 0, 0, 0, 0]
*/
// 调用flip()
b.flip();
// 容量:10,限制:3,位置:0
System.out.println("容量:"+b.capacity()+",限制:"+b.limit()+",位置:"+b.position());
System.out.println(Arrays.toString(b.array()));// [10, 20, 30, 0, 0, 0, 0, 0, 0, 0]
}
}