Java实现的一个高效的循环数据Buffer
2018-03-26 15:08
381 查看
在做一个项目时,需要用到一个字节数据池,意向中应满足以下特点:
1) 支持快速读写;
2) 不要做频繁的内存分配、释放(否则必然会影响速度);
然后,找啊找,在Java标准库中没有找到符合这两个条件的(当然很可能是有但我没找到)。
想了想,决定自己写一个。基本思路是:
1) 分配一块内存,且不再调整;
2) 以数据指针指向读写位置;
3) 一旦读写到内存尾,那么立即跳回头部继续读写;
完整源代码:
阅读上面的代码,可知这个工具类CircleBuffer,同时实现了两个标准Java接口DataInput和DataOutput。核心方法有三个:
1) 构造方法,用于管理内存(一次分配然后不用再管);
2) 读数据方法readByte,其中的核心在于:if (mReadPosition >= mCapacity) mReadPosition = 0;
3) 写数据方法writeByte,其中的核心在于:if (mWritePosition >= mCapacity) mWritePosition = 0;
其他的方法基本上都是readByte和writeByte的应用。
使用这个工具类,一边尽管往里写,另一边尽管往外读,不用担心冲突,不用担心内存溢出、资源回收甚至out of memory。
很简单吧。
1) 支持快速读写;
2) 不要做频繁的内存分配、释放(否则必然会影响速度);
然后,找啊找,在Java标准库中没有找到符合这两个条件的(当然很可能是有但我没找到)。
想了想,决定自己写一个。基本思路是:
1) 分配一块内存,且不再调整;
2) 以数据指针指向读写位置;
3) 一旦读写到内存尾,那么立即跳回头部继续读写;
完整源代码:
import java.io.DataInput; import java.io.DataOutput; import java.io.EOFException; import java.nio.charset.Charset; import java.util.Arrays; /** * 循环数据Buffer */ public class CircleBuffer implements DataInput, DataOutput { private static Charset UTF8_CHARSET = Charset.forName("UTF-8"); private byte[] mBuffer; private int mCapacity; private int mWritePosition; private int mReadableCount; private int mReadPosition; public CircleBuffer(int capacity) { mBuffer = new byte[capacity]; mCapacity = capacity; reset(); } @Override public boolean readBoolean() throws EOFException { return readByte() != 0; } @Override public byte readByte() throws EOFException { if (mReadableCount <= 0) throw new EOFException(); if (mReadPosition >= mCapacity) mReadPosition = 0; mReadableCount--; return mBuffer[mReadPosition++]; } @Override public char readChar() throws EOFException { return (char) ((readByte() << 8) | (readByte() & 0xFF)); } @Override public double readDouble() throws EOFException { return Double.longBitsToDouble(readLong()); } @Override public float readFloat() throws EOFException { return Float.intBitsToFloat(readInt()); } @Override public void readFully(byte[] dst) throws EOFException { for (int i = 0; i < dst.length; i++) { dst[i] = readByte(); } } @Override public void readFully(byte[] dst, int offset, int byteCount) throws EOFException { for (int i = 0; i < byteCount; i++) { dst[offset + i] = readByte(); } } @Override public int readInt() throws EOFException { return (((readByte() & 0xFF) << 24) | ((readByte() & 0xFF) << 16) | ((readByte() & 0xFF) << 8) | ((readByte() & 0xFF))); } @Override public String readLine() throws EOFException { byte[] buffer = new byte[1024]; int count = 0; while (true) { byte b = readByte(); if (b == '\r') continue; if (b == '\n') break; if (count >= buffer.length) { buffer = Arrays.copyOf(buffer, buffer.length * 2); } buffer[count++] = b; } return new String(buffer, 0, count); } @Override public long readLong() throws EOFException { 4000 return ((((long) readByte() & 0xFF) << 56) | (((long) readByte() & 0xFF) << 48) | (((long) readByte() & 0xFF) << 40) | (((long) readByte() & 0xFF) << 32) | (((long) readByte() & 0xFF) << 24) | (((long) readByte() & 0xFF) << 16) | (((long) readByte() & 0xFF) << 8) | (((long) readByte() & 0xFF))); } @Override public short readShort() throws EOFException { return (short) ((readByte() << 8) | (readByte() & 0xFF)); } @Override public int readUnsignedByte() throws EOFException { return readByte() & 0xFF; } @Override public int readUnsignedShort() throws EOFException { return (readByte() << 8) | (readByte() & 0xFF); } @Override public String readUTF() throws EOFException { int length = readInt(); byte[] values = new byte[length]; readFully(values); return new String(values, UTF8_CHARSET); } @Override public int skipBytes(int count) throws EOFException { for (int i = 0; i < count; i++) { readByte(); } return count; } @Override public void write(byte[] buffer) { for (int i = 0; i < buffer.length; i++) { writeByte(buffer[i]); } } @Override public void write(byte[] buffer, int offset, int count) { for (int i = 0; i < count; i++) { writeByte(buffer[offset + i]); } } @Override public void write(int oneByte) { writeByte(oneByte); } @Override public void writeBoolean(boolean val) { writeByte(val ? 1 : 0); } @Override public void writeByte(int val) { if (mWritePosition >= mCapacity) mWritePosition = 0; mReadableCount++; mBuffer[mWritePosition++] = (byte) val; } @Override public void writeBytes(String str) { byte[] bytes = str.getBytes(); write(bytes); } @Override public void writeChar(int val) { writeByte((val >>> 8) & 0xFF); writeByte((val >>> 0) & 0xFF); } @Override public void writeChars(String str) { writeBytes(str); } @Override public void writeDouble(double val) { writeLong(Double.doubleToLongBits(val)); } @Override public void writeFloat(float val) { writeInt(Float.floatToIntBits(val)); } @Override public void writeInt(int val) { writeByte((val >>> 24) & 0xFF); writeByte((val >>> 16) & 0xFF); writeByte((val >>> 8) & 0xFF); writeByte((val) & 0xFF); } @Override public void writeLong(long val) { writeByte((int) (val >>> 56) & 0xFF); writeByte((int) (val >>> 48) & 0xFF); writeByte((int) (val >>> 40) & 0xFF); writeByte((int) (val >>> 32) & 0xFF); writeByte((int) (val >>> 24) & 0xFF); writeByte((int) (val >>> 16) & 0xFF); writeByte((int) (val >>> 8) & 0xFF); writeByte((int) (val) & 0xFF); } @Override public void writeShort(int val) { writeByte((val >>> 8) & 0xFF); writeByte((val) & 0xFF); } @Override public void writeUTF(String str) { byte[] values = str.getBytes(UTF8_CHARSET); writeInt(values.length); write(values); } public void reset() { mReadableCount = 0; mReadPosition = 0; mWritePosition = 0; } public byte[] buffer() { return mBuffer; } public int capacity() { return mCapacity; } public int readable() { return mReadableCount; } }
阅读上面的代码,可知这个工具类CircleBuffer,同时实现了两个标准Java接口DataInput和DataOutput。核心方法有三个:
1) 构造方法,用于管理内存(一次分配然后不用再管);
2) 读数据方法readByte,其中的核心在于:if (mReadPosition >= mCapacity) mReadPosition = 0;
3) 写数据方法writeByte,其中的核心在于:if (mWritePosition >= mCapacity) mWritePosition = 0;
其他的方法基本上都是readByte和writeByte的应用。
使用这个工具类,一边尽管往里写,另一边尽管往外读,不用担心冲突,不用担心内存溢出、资源回收甚至out of memory。
很简单吧。
相关文章推荐
- Java 螺旋数组的实现方式-一个循环实现哦
- java实现从一个数据库查询数据经过处理导入另外一个数据库中
- 用最简单的函数实现功能:判断一个int数据是否是2的x次幂(不能使用循环)。
- [原创][Java]一个简单高效的线程安全队列的JAVA实现
- 【java基础 4】树形结构数据呈现的非递归算法(循环)实现
- java实现一个简单的机器学习和数据挖掘的demo
- 【java基础 4】树形结构数据呈现的非递归算法(循环)实现
- How:What:Java 中实现readLine()(逐行读取数据)的一个实例
- 一个定时往mysql写数据的java类的设计与实现
- 数据结构(三)---双向循环链表的实现---java版
- 一个将数据文件转换成excel文件打印的java实现方法的代码片断(Struts+poi)
- 在一个程序中需要用到全局变量(在多个class之间共享数据),请问如何定义具有这种功能的变量?或者是否有其他的方法解决多个class之间的数据共享(尽量简单实现)。 首先应该明确 Java中没有全局变
- opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类
- 将后台数据读取到前台的EXCEL文件中去,用javascript实现,asp.net,javacript(发一个原创)
- C# 实现高效的 数据组包和拆包处理器,使用循环缓冲区处理
- java 实现查询一个数据表中记录总数
- fastjson:实现对java.nio.ByteBuffer数据类型的支持
- 用Java 实现一个表中的数据复制到另一个表中
- java 实现查询一个数据表中记录总数
- (旋转数组问题)给定一个整数类型的循环有序数组,求循环数组的特定值,使用二分查找法(JAVA实现)