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

    }
}

java中buf java中buffere_数据结构


位置-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]

    }
}

笔记如有错误之处,请各位大佬指正,欢迎评论留言,不胜感激!!!