ByteBuffer 中可以通过4个索引高效操作数据,它们分别是:mark(标记)、position(位置)、limit(界限)、capacity(容量)。

下表是具体操作这些索引的方法:

方法名

用途

capacity()

返回缓冲区容量

clear()

清空缓冲区,将 position 设置为0,limit 设置为 capacity。可以通过此方法覆写缓冲区

flip()

将 limit 设置为 position ,position 设置为0。此方法用于准备从缓冲区读取数据

limit()

返回 limit 的值

limit(int newLimit)

设置 limit 的值

mark()

将 mark 设置为 position

position()

返回 position 的值

position(int newPosition)

设置 position 的值

remaining()

返回 ( limit - newPosition )

hasRemaining()

若有介于 postion 和 limit 之间的元素,则返回 true

初看这些方法可能会有点摸不着头脑,下面我们一起学习一个简单的例子:交换相邻字符,以便于加深理解。

public class UsingBuffers {

    private static void symmetricScramble(CharBuffer buffer) {
        while (buffer.hasRemaining()) {
            //设置标记
            buffer.mark();
            //获取后续2个字符
            char c1 = buffer.get();
            char c2 = buffer.get();
            //将position设置为mark
            buffer.reset();
            //交替覆写字符
            buffer.put(c2).put(c1);
        }
    }

    public static void main(String[] args) {
        char[] data = "UsingBuffers".toCharArray();
        //创建指定大小的缓冲器
        ByteBuffer bb = ByteBuffer.allocate(data.length * 2);
        CharBuffer cb = bb.asCharBuffer();
        //写入数据
        cb.put(data);
        System.out.println(cb.rewind());
        //交换相邻字符
        symmetricScramble(cb);
        System.out.println(cb.rewind());
        //再次交换相邻字符
        symmetricScramble(cb);
        System.out.println(cb.rewind());
    }

}
UsingBuffers
sUniBgfuefsr
UsingBuffers

因一个 char 类型占2个字节,故创建 char 个数 * 2 字节大小的缓冲器,刚好能容纳所有字符。

缓冲器创建好时如下图:

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_java


position 指向第一个元素,capacity 和 limit 指向最后一个元素。

当我们调用 get() 和 put() 方法时,position 指针会依次向后移动,但通过指定下标的方式调用 get(int index)put(int index, char c) 并不会改变下标的位置。

在 while 循环中,使用 mark() 将 mark 标记为 position 的位置时,缓冲器如下图:

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_nio_02


调用2次 get() 方法后,position 指针向后移动2次, position 此时的位置如下图:

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_nio_03


为了能够交换2个相邻位置的值,我们需要把 c2 写入前一个位置, c1 写入后一个位置,这里可以使用 put(int index, char c) 指定绝对位置来实现,但本例通过 reset() 方法,把 position 设置为 mark 的位置,再重新依次覆写,已达到相同的目的,如下图所示:

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_IO_04


交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_IO_05


之后,进入下一个循环,在此将 mark 设置到 position 的位置。

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_开发语言_06


等循环完成,position 会移动至缓冲器末尾。

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_java_07


如果需要打印出缓冲器中的全部内容,则需要调用 rewind() 将 position 移动至起始位置,此方法同时也会舍弃 mark 标记。

交换两个字符变量的值并输出 JavaScript 交换两个字符的位置_后端_08


此时再打印 CharBuffer 会得到 position 至 limit 之间的全部内容,再次调用 symmetricScramble() 则可以将交换后的内容复原。


本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!