⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arraybytelist.java

📁 sea是一个基于seda模式的实现。这个设计模式将系统分为很多stage。每个stage分布不同的任务(基于线程池)。通过任务流的方式提高系统的效率。
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (c) 2003, The Regents of the University of California, through
 * Lawrence Berkeley National Laboratory (subject to receipt of any required
 * approvals from the U.S. Dept. of Energy). All rights reserved.
 */
package gov.lbl.dsd.sea.nio.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.util.BitSet;

/**
Efficient resizable auto-expanding list holding <code>byte</code> elements; implemented with arrays. 
The API is intended for easy non-trivial high-throughput processing, 
and (in an elegant and compact yet different form) provides all list and set functionality 
of the java.util collections package, as well as a little more.
This API fills the gap between raw arrays (non-resizable), nio ByteBuffers (non-resizable) and
java.util.List and java.util.Set (resizable but not particularly useful for 
<i>non-trivial high-throughput</i> processing on primitive types).
For example, this class is convenient to parse and/or assemble 
variable-sized network messages if message lengths are a priori unknown.
<p>
Indexed element access is zero based: valid indexes range from 
index <code>0</code> (inclusive) to index <code>list.size()</code> (exclusive).
Attempts to access out-of-range indexes will throw an {@link IndexOutOfBoundsException}.
<p>
<strong>Note that this implementation is not synchronized, hence not inherently thread safe.</strong>
<p>
Example usage:
<pre>
System.out.println(new ArrayByteList(new byte[] {0,1,2}));

// insert and replace
ArrayByteList demo = new ArrayByteList(new byte[] {0,1,2});
demo.replace(0,0, new byte[] {4,5}); // insert
System.out.println(demo); // yields [4,5,0,1,2]
demo.replace(0,2, new byte[] {6,7,8,9});
System.out.println(demo); // yields [6,7,8,9,0,1,2]

// sort, search and remove
System.out.println(demo.subList(1,3)); // yields [7,8]
demo.sort(true);
System.out.println(demo);
System.out.println(demo.binarySearch((byte) 7));
demo.remove(4, 4+1); // remove elem at index 4
System.out.println(demo);
System.out.println(demo.binarySearch((byte) 7));

// efficient file I/O
System.out.println(new ArrayByteList(0).add(new java.io.FileInputStream("/etc/passwd")).toString(null));
new java.io.FileOutputStream("/tmp/test").write(demo.asArray(), 0, demo.size());
System.out.println(new ArrayByteList(0).add(new java.io.FileInputStream("/tmp/test")));
System.out.println(new ArrayByteList(0).add(new java.io.FileInputStream("/tmp/test").getChannel()));

// network I/O via stream
java.nio.charset.Charset charset = java.nio.charset.Charset.forName("ISO-8859-1");
System.out.println(new ArrayByteList(0).add(new java.net.URL("http://www.google.com").openStream()).toString(charset));

// simple HTTP via raw socket channel
java.nio.channels.SocketChannel channel = java.nio.channels.SocketChannel.open();
channel.connect(new java.net.InetSocketAddress("www.google.com", 80));
channel.write(new ArrayByteList("GET / HTTP/1.0" + "\r\n\r\n", charset).asByteBuffer());
System.out.println(new ArrayByteList(0).add(channel).toString(charset));
</pre>
<p>
Manipulating primitive values other than bytes is not directly
supported. However, this can be done via <code>asByteBuffer()</code> 
along the following lines:
<pre>
    // get and set 4 byte integer value at end of list:
    list = ...
    int val = list.asByteBuffer().getInt(list.size() - 4);
    list.asByteBuffer().setInt(list.size() - 4, val * 10);
	
    // append 8 byte double value:
    list = ...
    double elemToAdd = 1234.0;
    list.replace(list.size(), list.size(), (byte)0, 8); // add 8 bytes at end
    list.asByteBuffer().putDouble(list.size() - 8, elemToAdd);
 
    // insert 8 byte double value at beginning:
    list = ...
    double elemToInsert = 1234.0;
    list.replace(0, 0, 0, 8); // insert 8 bytes at beginning
    list.asByteBuffer().putDouble(0, elemToInsert); 
</pre>
This class requires JDK 1.4 or higher; otherwise it has zero dependencies. 
Hence you can simply copy the file into your own project if minimal dependencies are desired.
<p>
Also note that the compiler can (and will) easily inline all methods, then optimize away.
In fact with the Sun jdk-1.4.2 server VM it is hard to measure any difference 
to raw array manipulations at abstraction level zero.

@author whoschek@lbl.gov
@author $Author: hoschek3 $
@version $Revision: 1.52 $, $Date: 2004/12/01 21:00:24 $
*/
public final class ArrayByteList implements java.io.Serializable {

	/**
	 * The array into which the elements of the list are stored. The
	 * capacity of the list is the length of this array.
	 */
	private transient byte[] elements;

	/**
	 * The current number of elements contained in this list.
	 */
	private int size;
	
	/**
	 * For compatibility across versions
	 */
	private static final long serialVersionUID = -6250350905005960078L;
		
	/**
	 * The default charset is UTF-8, and fixed for interoperability.
	 * Note that the first 128 character codes of UTF-8, ISO-8859-1 and US-ASCII are identical.
	 * Hence these charsets are equivalent for most practical purposes.
	 * This charset is used on most operating systems (e.g. for system files, config files, log files, scripts, source code, etc.)
	 * Note that in Java UTF-8 and ISO-8859-1 always works since JDK support for it is required by the JDK spec.   
	 */
	private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
	
	/**
	 * Constructs an empty list.
	 */
	public ArrayByteList() {
		this(64);
	}

	/**
	 * Constructs an empty list with the specified initial capacity.
	 * 
	 * @param initialCapacity
	 *            the number of elements the receiver can hold without
	 *            auto-expanding itself by allocating new internal memory.
	 */
	public ArrayByteList(int initialCapacity) {
		elements = new byte[initialCapacity];
		size = 0;
	}

	/**
	 * Constructs a list SHARING the specified elements. The initial size and
	 * capacity of the list is the length of the backing array.
	 * <p>
	 * <b>WARNING: </b> For efficiency reasons and to keep memory usage low,
	 * <b>the array is SHARED, not copied </b>. So if subsequently you modify
	 * the specified array directly via the [] operator, be sure you know what
	 * you're doing.
	 * <p>
	 * If you rather need copying behaviour, use
	 * <code>copy = new ArrayByteList(byte[] elems).copy()</code> or similar.
	 * <p>
	 * If you need a list containing a copy of <code>elems[from..to)</code>, use
	 * <code>list = new ArrayByteList(to-from).add(elems, from, to-from)</code> 
	 * or <code>list = new ArrayByteList(ByteBuffer.wrap(elems, from, to-from))</code>
	 * or similar.
	 * 
	 * @param elems
	 *            the array backing the constructed list
	 */
	public ArrayByteList(byte[] elems) {
		elements = elems;
		size = elems.length;
	}

	/**
	 * Constructs a list containing a copy of the remaining buffer elements. The
	 * initial size and capacity of the list is <code>elems.remaining()</code>.
	 * 
	 * @param elems
	 *            the elements initially to be added to the list
	 */
	public ArrayByteList(ByteBuffer elems) {
		this(elems.remaining());
		add(elems);
	}

	/**
	 * Constructs a list containing a copy of the encoded form of the given
	 * char sequence (String, StringBuffer, CharBuffer, etc).
	 * 
	 * @param str
	 *            the string to convert.
	 * @param charset
	 *            the charset to convert with (e.g. <code>Charset.forName("US-ASCII")</code>,
	 *            <code>Charset.forName("ISO-8859-1")</code>). 
	 *            If <code>null</code> uses <code>Charset.forName("UTF-8")</code> as the default charset.
	 */
	public ArrayByteList(CharSequence str, Charset charset) {
		this(getCharset(charset).encode(CharBuffer.wrap(str)));
	}

	/**
	 * Appends the specified element to the end of this list.
	 * 
	 * @param elem
	 *            element to be appended to this list.
	 * @return <code>this</code> (for chaining convenience only)
	 */
	public ArrayByteList add(byte elem) {
		if (size == elements.length) ensureCapacity(size + 1);
		elements[size++] = elem;
		return this;
		// equally correct alternative impl: insert(size, elem);
	}

	/**
	 * Appends the elements in the range <code>[offset..offset+length)</code> to the end of this list.
	 * 
	 * @param elems the elements to be appended
	 * @param offset the offset of the first element to add (inclusive)
	 * @param length the number of elements to add
	 * @return <code>this</code> (for chaining convenience only)
	 * @throws IndexOutOfBoundsException if indexes are out of range.
	 */
	public ArrayByteList add(byte[] elems, int offset, int length) {
		if (offset < 0 || length < 0 || offset + length > elems.length) 
			throw new IndexOutOfBoundsException("offset: " + offset + ", length: " + length + ", elems.length: " + elems.length);
		ensureCapacity(size + length);
		System.arraycopy(elems, offset, this.elements, size, length);
		size += length;
		return this;
		// equally correct alternative impl: replace(size, size, elems, offset, length);
	}

	/**
	 * Appends the specified elements to the end of this list.
	 * 
	 * @param elems
	 *            elements to be appended.
	 * @return <code>this</code> (for chaining convenience only)
	 */
	public ArrayByteList add(ArrayByteList elems) {
		replace(size, size, elems);
		return this;
	}
	
	/**
	 * Appends the remaining buffer elements to the end of this list.
	 * 
	 * @param elems
	 *            elements to be appended.
	 * @return <code>this</code> (for chaining convenience only)
	 */
	public ArrayByteList add(ByteBuffer elems) {
		int length = elems.remaining();
		ensureCapacity(size + length);
		elems.get(this.elements, size, length);
		size += length;
		return this;
		// equally correct alternative impl: replace(size, size, elems, elems.remaining());
	}
	
	/**
	 * Appends the encoded form of the given char sequence (String, StringBuffer, CharBuffer, etc).
	 * 
	 * @param str
	 *            the string to convert.
	 * @param charset
	 *            the charset to convert with (e.g. <code>Charset.forName("US-ASCII")</code>,
	 *            <code>Charset.forName("ISO-8859-1")</code>). 
	 *            If <code>null</code> uses <code>Charset.forName("UTF-8")</code> as the default charset.
	 * @return <code>this</code> (for chaining convenience only)
	 */
	public ArrayByteList add(CharSequence str, Charset charset) {
		return add(getCharset(charset).encode(CharBuffer.wrap(str)));
	}

	/**
	 * Appends the remaining elements of the stream to the end of this list,
	 * reading until end-of-stream. Finally closes the stream. Note that the
	 * implementation is efficient even if the input stream is not a buffered
	 * stream.
	 * 
	 * @param elems
	 *            the input stream to read from.
	 * @return <code>this</code> (for chaining convenience only)
	 * @throws IOException
	 *             if an I/O error occurs.
	 */
	public ArrayByteList add(InputStream elems) throws IOException {
		// Note that our algo is correct and efficient even if
		// the input stream implements available() in weird or buggy ways.
		try {
			ensureCapacity(size + 1 + Math.max(0, elems.available()));
			int n;
			while ((n = elems.read(elements, size, elements.length - size)) >= 0) {
				size += n;
				// increasingly make room for next read (and defensively 
				// ensure we don't spin loop, attempting to read zero bytes per iteration)
				ensureCapacity(size + Math.max(1, elems.available()));
			}
		} 
		finally {
			if (elems != null) elems.close();
		}
		return this;
	}

	/**
	 * Appends the remaining elements of the channel to the end of this list,
	 * reading until end-of-stream. Finally closes the channel.
	 * 
	 * @param elems
	 *            the channel to read from.
	 * @return <code>this</code> (for chaining convenience only)
	 * @throws IOException
	 *             if an I/O error occurs.
	 */
	public ArrayByteList add(ReadableByteChannel elems) throws IOException {
		try {
			int remaining = 8192;
			if (elems instanceof FileChannel) { // we can be more efficient
				long rem = ((FileChannel) elems).size() - ((FileChannel) elems).position();
				if (size + 1 + rem > Integer.MAX_VALUE) throw new IllegalArgumentException("File channel too large (2 GB limit exceeded)");
				remaining = (int) rem;
			}
			ensureCapacity(size + 1 + remaining);
			int n;
			while ((n = elems.read(ByteBuffer.wrap(elements, size, elements.length - size))) >= 0) {
				size += n;
				// increasingly make room for next read (and defensively 
				// ensure we don't spin loop, attempting to read zero bytes per iteration)
				ensureCapacity(size + 1);
			}
		}
		finally {
			if (elems != null) elems.close();
		}
		return this;
	}
	
	/**
	 * Returns the elements currently stored, including invalid elements between
	 * size and capacity, if any.
	 * <p>
	 * <b>WARNING: </b> For efficiency reasons and to keep memory usage low,
	 * <b>the array is SHARED, not copied </b>. So if subsequently you modify the
	 * returned array directly via the [] operator, be sure you know what you're
	 * doing.
	 * 
	 * @return the elements currently stored.
	 */
	public byte[] asArray() {
		return elements;
	}

	/**
	 * Returns a buffer SHARING elements with the receiver. The buffer will
	 * have the default NIO byte order, which is ByteOrder.BIG_ENDIAN.
	 * <p>
	 * <b>WARNING: </b> For efficiency reasons and to keep memory usage low,
	 * <b>the array is SHARED, not copied </b>. So if subsequently you modify the
	 * returned buffer, be sure you know what you're doing.
	 */
	public ByteBuffer asByteBuffer() {
		return ByteBuffer.wrap(elements, 0, size);
	}

	/**
	 * Creates and returns an unsynchronized output stream that appends to this
	 * SHARED backing byte list. Useful if legacy code requires adapting to a
	 * stream based interface. Note: This is more efficient and
	 * straighforward than using a {@link java.io.ByteArrayOutputStream}.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -