/** * Circular chained byte array * * @author bbwang8088@126.com */ public class CircularChainedBuffer { enum ACTION { WAIT, READ, WRITE } private ACTION lastAction = ACTION.WAIT; // current write position private int wPos = 0; // current read position private int rPos = 0; // byte array private byte[] buffer = null; // byte array length private int length = 0; public CircularChainedBuffer(int size) { this.length = size; init(); } /** * initialize method */ private void init() { this.buffer = new byte[this.length]; this.wPos = 0; this.rPos = 0; this.lastAction = ACTION.WAIT; } /** * reset method */ public void reset() { init(); } /** * Get current writable data size. * * @return */ public int getWritableSize() { int ret = 0; // if initialize, return length of buffer array. if (this.wPos == 0 && this.rPos == 0) { return this.length; } ret = this.wPos - this.rPos; // normal case. if (ret > 0) { ret = this.length - ret; } // same position of read and write. else if (ret == 0) { // write to same position,then cann't write any more. if (this.lastAction == ACTION.WRITE) { ret = 0; } // read to same position,then cann't read any more, array is empty. else if (this.lastAction == ACTION.READ) { ret = this.length; } } // if read position before write position, then calculate against. else { ret = this.rPos - this.wPos; } return ret; } /** * Get current readable data size. * * @return */ public int getReadableSize() { return this.length - this.getWritableSize(); } /** * Try to write some data, if cann't write all, then write a part, if buffer * is filled, then return 0. * * @param data * @return return size of wrote data */ public synchronized int tryWrite(byte[] data) { int retValue = 0; int tmpWritableSize = this.getWritableSize(); // if current writable size is 0, then return 0. if (tmpWritableSize == 0) { return 0; } int copyLength = 0; if (data.length > tmpWritableSize) { copyLength = tmpWritableSize; } else { copyLength = data.length; } // write position after read position. if (this.wPos >= this.rPos) { // all data can write from current write position to end of array, // no need to write data back to head of buffer array. if ((this.wPos + copyLength) <= this.length) { // copy all data of parameter array to buffer array. System.arraycopy(data, 0, this.buffer, this.wPos, copyLength); // move write position. this.wPos += copyLength; } // copy part of parameter array full fill buffer array from write // position, // then copy left part of parameter array from head of buffer array. else { int partA = (this.length - this.wPos); int partB = copyLength - partA; // copy part of parameter array full fill buffer array from // write position System.arraycopy(data, 0, this.buffer, this.wPos, partA); // copy left part of parameter array from head of buffer array System.arraycopy(data, partA, this.buffer, 0, partB); // move write position this.wPos = partB; } } // read position after write position else { // can only write data between write position and read position System.arraycopy(data, 0, this.buffer, this.wPos, copyLength); // move write position this.wPos += copyLength; } retValue = copyLength; this.lastAction = ACTION.WRITE; return retValue; } /** * Try to read size of data,return real read data, if no data can read then * return null. * * @param size * @return return byte array of read data */ public synchronized byte[] tryRead(int size) { byte[] ret = null; int tmpReadableSize = this.getReadableSize(); if (tmpReadableSize == 0 || size <= 0) { return new byte[0]; } int realReadLength = 0; if (size > tmpReadableSize) { realReadLength = tmpReadableSize; } else { realReadLength = size; } ret = new byte[realReadLength]; // write position after read position. if (this.rPos < this.wPos) { System.arraycopy(this.buffer, this.rPos, ret, 0, realReadLength); this.rPos += realReadLength; } // read position after write position else { if( (this.rPos +realReadLength ) <= this.length){ System.arraycopy(this.buffer, this.rPos, ret, 0, realReadLength); this.rPos += realReadLength; }else{ int partA = (this.length - this.rPos); int partB = realReadLength - partA; //Log.d(this.getClass().getSimpleName(),"size:"+size+" realReadLength"+realReadLength+" this.length:"+this.length+" this.rPos:"+this.rPos+" this.wPos:"+this.wPos+" partA:"+partA+" partB:"+partB); // copy part of parameter array full fill buffer array from write // position System.arraycopy(this.buffer, this.rPos, ret, 0, partA); // copy left part of parameter array from head of buffer array System.arraycopy(this.buffer, 0, ret, partA, partB); // move write position this.rPos = partB; } } this.lastAction = ACTION.READ; return ret; } /** * Attation: this method will not move read position. Try to read size of * data,return real read data, if no data can read then return null. * * @param size * @return return byte array of read data */ public synchronized byte[] pretendRead(int size) { byte[] ret = null; int tmpReadableSize = this.getReadableSize(); if (tmpReadableSize == 0) { return new byte[0]; } int realReadLength = 0; if (size > tmpReadableSize) { realReadLength = tmpReadableSize; } else { realReadLength = size; } ret = new byte[realReadLength]; // write position after read position. if (this.rPos < this.wPos) { System.arraycopy(this.buffer, this.rPos, ret, 0, realReadLength); // this.rPos += realReadLength; } // read position after write position else { int partA = (this.length - this.rPos); int partB = realReadLength - partA; // copy part of parameter array full fill buffer array from write // position System.arraycopy(this.buffer, this.rPos, ret, 0, partA); // copy left part of parameter array from head of buffer array System.arraycopy(this.buffer, 0, ret, partA, partB); // move write position // this.rPos = partB; } // this.lastAction = ACTION.READ; return ret; } public synchronized byte[] pretendReadAll() { return this.pretendRead(this.getReadableSize()); } /** * Attation: this method will not move read position. Try to read size of * data,return real read data, if no data can read then return null. * * @param size * @return return byte array of read data */ public synchronized byte[] pretendRead(int offset, int size) { byte[] data = new byte[size]; System.arraycopy(pretendReadAll(), offset, data, 0, size); return data; } public synchronized byte[] readAll() { return this.tryRead(this.getReadableSize()); } public String toString() { StringBuffer sb = new StringBuffer(); for (byte b : this.buffer) { sb.append(" " + Integer.toHexString(b & 0xFF)); } return sb.toString(); } }
import static org.junit.Assert.*; import org.junit.Test; /** * Tester for Circular chained byte array * * @author bbwang8088@126.com */ public class TestCycleByteArray { @Test public void TestGetWritableSize() { int size = 4096; CircularChainedBuffer buffer = new CircularChainedBuffer(size); assertEquals(buffer.getWritableSize(), size); byte[] data1_size10 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a }; byte[] data2_size10 = { (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa }; // byte[] data3_size10 = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, // (byte) 0xff }; buffer.tryWrite(data1_size10); assertEquals(size - data1_size10.length, buffer.getWritableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); // System.out.println(buffer.toString()); buffer.tryWrite(data2_size10); assertEquals(size - data2_size10.length * 2, buffer.getWritableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); // System.out.println(buffer.toString()); byte[] data = buffer.tryRead(data2_size10.length * 2); // System.out.println(new String(data)); assertEquals(size, buffer.getWritableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); // System.out.println(buffer.toString()); data = buffer.tryRead(data2_size10.length * 2); assertEquals(0, data.length); // System.out.println(new String(data)); // System.out.println(buffer.toString()); for (int i = 0; i < (size / data1_size10.length); i++) { assertEquals(data1_size10.length, buffer.tryWrite(data1_size10));// 1 // System.out.println(buffer.toString()); } assertEquals(size % data1_size10.length, buffer.getWritableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); data = buffer.tryRead(size*2); assertEquals(size-size%data1_size10.length, data.length); assertEquals(size, buffer.getWritableSize()); assertEquals(0, buffer.getReadableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); assertEquals(data1_size10.length, buffer.tryWrite(data1_size10)); assertEquals(data2_size10.length, buffer.tryWrite(data2_size10)); assertEquals(size - data1_size10.length * 2, buffer.getWritableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); data = buffer.tryRead(data1_size10.length*2); assertEquals(data1_size10.length*2, data.length); assertEquals(size, buffer.getWritableSize()); assertEquals(0, buffer.getReadableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); for (int i = 0; i < (size / data1_size10.length); i++) { assertEquals(data1_size10.length, buffer.tryWrite(data1_size10));// 1 } assertEquals(size % data1_size10.length, buffer.getWritableSize()); assertEquals(size-size % data1_size10.length, buffer.getReadableSize()); assertEquals(size, buffer.getWritableSize() + buffer.getReadableSize()); assertEquals(size % data1_size10.length, buffer.tryWrite(data1_size10));// 1 data = buffer.readAll(); assertEquals(size, buffer.getWritableSize()); assertEquals(0, buffer.getReadableSize()); } }
相关推荐
循环链表 实现约瑟夫环 java 自己写的 测试通过 有注释
用Java定义一个循环链表,实现链表的基本操作: 初始化*、获取头结点、添加新元素*、删除链表元素 、获取链表元素*、查找链表元素*、更新链表中某个元素、 判断链表是否为空、求链表元素个数、输出链表元素、清空...
总之,循环链表在Java中的实现涉及节点类的设计和链表类的操作方法。理解并掌握循环链表的特性对于解决一些特定问题,如判断链表是否有环、高效地遍历数据等,是非常重要的。通过阅读和实践提供的`LinkedList.java`...
在Java编程中,我们可以使用面向对象的设计思想来实现循环双链表。通常,这样的数据结构会包含三个主要部分:一个接口定义链表的基本操作,一个类实现这个接口来构建具体的链表结构,还有一个测试类用于验证链表功能...
在Java中实现循环链表,我们需要定义一个节点类(Node)来存储数据和指向下一个节点的引用,同时在链表类(CircularLinkedList)中维护头节点和当前大小。以下是实现的关键点: 1. **节点类(Node)**:创建一个内部...
由于在项目中需要用到循环链表,然而在JDK没有其实现,所以用Java语言实现了循环链表,供大家学习和参考。若有任何问题请发送E-Mail:wn_lut@126.com,以交流及改进。 Package:com.utilities.structs 打开方式:...
下面我们将详细讨论循环链表的基本概念,以及如何使用C、C++和JAVA三种语言来实现它。 ### 循环链表基本概念 1. **节点结构**:每个链表节点包含两部分,数据域存储实际数据,指针域存储指向下一个节点的指针。在...
Java 双向循环链表是一种数据结构,它包含前后两个指针,每个节点都有一个指向其前一个节点的引用和一个指向其后一个节点的引用。这种数据结构允许我们在链表的任何位置进行高效的插入和删除操作。在给定的程序中,...
本话题主要关注的是Java中的链表实现,特别是循环链表的模板类设计。循环链表与普通链表的主要区别在于最后一个节点指向了头节点,形成一个闭合的环,这在处理循环遍历或某些特定算法时非常方便。 首先,让我们详细...
非循环链表的尾部没有链接回头部,因此遍历链表时,当到达尾部的后继为空时,即可停止,避免了无限循环的风险。这对于编写遍历或搜索算法来说,简化了逻辑处理。 四、Java实现 在Java中,双向链表可以使用内置的`...
在这个压缩包文件“单向循环链表.zip”中,包含了两个源代码文件——LoopSingle.java和List.java,它们分别对应了单向循环链表的节点类和接口定义。 首先,我们来看`LoopSingle.java`,这个文件通常会包含一个名为`...
JAVA实现链表_双向链表
类似约瑟夫环问题。有一群人组成一个圈。从头开始按照顺时针方向从1开始依次报数。报到到9的人就离开圈子。其左手边的人接着从1开始报数。依此进行,直到剩最后一个人为止。
其中,循环链表是一种常用的数据结构,它通过链式存储方式形成一个没有头尾之分的闭合结构,非常适合用来模拟这种环形排列的问题。 循环链表由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在Java中,...
在这个问题中,我们可以通过创建一个循环链表来模拟猴子围成的圈子,每只猴子对应一个节点。首先,我们需要创建一个方法用于添加猴子到链表: ```java public void addMonkey(int pos, int val) { ListNode new...
约瑟夫环,用循环链表实现,语言为Java。假设数到三的数出列。程序输出1到10的出列顺序。
在Java编程中,双向循环链表是一种特殊的数据结构,它包含指向前后节点的引用,使得在链表中进行正向和反向遍历都变得容易。在这个程序中,作者实现了一个名为`BothwayLoopLinked`的类来表示双向循环链表。这个类...
Java 数组链表效率对比 Java 中的数组和链表是两种常用的数据结构,它们都可以用来存储和操作数据。然而,在实际开发中,选择合适的数据结构和遍历方式对程序的性能和效率有着非常重要的影响。下面我们将对 Java 中...