📄 objecttable.java
字号:
/* ========================================================================
* JCommon : a free general purpose class library for the Java(tm) platform
* ========================================================================
*
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jcommon/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ----------------
* ObjectTable.java
* ----------------
* (C) Copyright 2003, 2004, by Object Refinery Limited.
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): -;
*
* $Id: ObjectTable.java,v 1.8 2005/10/18 13:24:19 mungady Exp $
*
* Changes
* -------
* 29-Apr-2003 : Version 1, based on PaintTable class (DG);
* 21-May-2003 : Copied the array based implementation of StrokeTable and
* fixed the serialisation behaviour (TM).
*/
package org.jfree.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
/**
* A lookup table for objects. This implementation is not synchronized,
* it is up to the caller to synchronize it properly.
*
* @author Thomas Morgner
*/
public class ObjectTable implements Serializable {
/** For serialization. */
private static final long serialVersionUID = -3968322452944912066L;
/** The number of rows. */
private int rows;
/** The number of columns. */
private int columns;
/** An array of objects. The array may contain <code>null</code> values. */
private transient Object[][] data;
/**
* Defines how many object-slots get reserved each time we run out of
* space.
*/
private int rowIncrement;
/**
* Defines how many object-slots get reserved each time we run out of
* space.
*/
private int columnIncrement;
/**
* Creates a new table.
*/
public ObjectTable() {
this (5, 5);
}
/**
* Creates a new table.
*
* @param increment the row and column size increment.
*/
public ObjectTable(final int increment) {
this (increment, increment);
}
/**
* Creates a new table.
*
* @param rowIncrement the row size increment.
* @param colIncrement the column size increment.
*/
public ObjectTable(final int rowIncrement, final int colIncrement) {
if (rowIncrement < 1) {
throw new IllegalArgumentException("Increment must be positive.");
}
if (colIncrement < 1) {
throw new IllegalArgumentException("Increment must be positive.");
}
this.rows = 0;
this.columns = 0;
this.rowIncrement = rowIncrement;
this.columnIncrement = colIncrement;
this.data = new Object[rowIncrement][];
}
/**
* Returns the column size increment.
*
* @return the increment.
*/
public int getColumnIncrement() {
return this.columnIncrement;
}
/**
* Returns the row size increment.
*
* @return the increment.
*/
public int getRowIncrement() {
return this.rowIncrement;
}
/**
* Checks that there is storage capacity for the specified row and resizes
* if necessary.
*
* @param row the row index.
*/
protected void ensureRowCapacity (final int row) {
// does this increase the number of rows? if yes, create new storage
if (row >= this.data.length) {
final Object[][] enlarged = new Object[row + this.rowIncrement][];
System.arraycopy(this.data, 0, enlarged, 0, this.data.length);
// do not create empty arrays - this is more expensive than checking
// for null-values.
this.data = enlarged;
}
}
/**
* Ensures that there is storage capacity for the specified item.
*
* @param row the row index.
* @param column the column index.
*/
public void ensureCapacity (final int row, final int column) {
if (row < 0) {
throw new IndexOutOfBoundsException("Row is invalid. " + row);
}
if (column < 0) {
throw new IndexOutOfBoundsException("Column is invalid. " + column);
}
ensureRowCapacity(row);
final Object[] current = this.data[row];
if (current == null) {
final Object[] enlarged
= new Object[Math.max (column + 1, this.columnIncrement)];
this.data[row] = enlarged;
}
else if (column >= current.length) {
final Object[] enlarged = new Object[column + this.columnIncrement];
System.arraycopy(current, 0, enlarged, 0, current.length);
this.data[row] = enlarged;
}
}
/**
* Returns the number of rows in the table.
*
* @return The row count.
*/
public int getRowCount() {
return this.rows;
}
/**
* Returns the number of columns in the table.
*
* @return The column count.
*/
public int getColumnCount() {
return this.columns;
}
/**
* Returns the object from a particular cell in the table.
* Returns null, if there is no object at the given position.
* <P>
* Note: throws IndexOutOfBoundsException if row or column is negative.
*
* @param row the row index (zero-based).
* @param column the column index (zero-based).
*
* @return The object.
*/
protected Object getObject(final int row, final int column) {
if (row < this.data.length) {
final Object[] current = this.data[row];
if (current == null) {
return null;
}
if (column < current.length) {
return current[column];
}
}
return null;
}
/**
* Sets the object for a cell in the table. The table is expanded if
* necessary.
*
* @param row the row index (zero-based).
* @param column the column index (zero-based).
* @param object the object.
*/
protected void setObject(final int row, final int column,
final Object object) {
ensureCapacity(row, column);
this.data[row][column] = object;
this.rows = Math.max (this.rows, row + 1);
this.columns = Math.max (this.columns, column + 1);
}
/**
* Tests this paint table for equality with another object (typically also
* an <code>ObjectTable</code>).
*
* @param o the other object.
*
* @return A boolean.
*/
public boolean equals(final Object o) {
if (o == null) {
return false;
}
if (this == o) {
return true;
}
if ((o instanceof ObjectTable) == false) {
return false;
}
final ObjectTable ot = (ObjectTable) o;
if (getRowCount() != ot.getRowCount()) {
return false;
}
if (getColumnCount() != ot.getColumnCount()) {
return false;
}
for (int r = 0; r < getRowCount(); r++) {
for (int c = 0; c < getColumnCount(); c++) {
if (ObjectUtilities.equal(getObject(r, c),
ot.getObject(r, c)) == false) {
return false;
}
}
}
return true;
}
/**
* Returns a hash code value for the object.
*
* @return the hashcode
*/
public int hashCode() {
int result;
result = this.rows;
result = 29 * result + this.columns;
return result;
}
/**
* Handles serialization.
*
* @param stream the output stream.
*
* @throws java.io.IOException if there is an I/O problem.
*/
private void writeObject(final ObjectOutputStream stream)
throws IOException {
stream.defaultWriteObject();
final int rowCount = this.data.length;
stream.writeInt(rowCount);
for (int r = 0; r < rowCount; r++) {
final Object[] column = this.data[r];
stream.writeBoolean(column != null);
if (column != null) {
final int columnCount = column.length;
stream.writeInt(columnCount);
for (int c = 0; c < columnCount; c++) {
writeSerializedData(stream, column[c]);
}
}
}
}
/**
* Handles the serialization of an single element of this table.
*
* @param stream the stream which should write the object
* @param o the object that should be serialized
* @throws IOException if an IO error occured
*/
protected void writeSerializedData(final ObjectOutputStream stream,
final Object o)
throws IOException {
stream.writeObject(o);
}
/**
* Restores a serialized object.
*
* @param stream the input stream.
*
* @throws java.io.IOException if there is an I/O problem.
* @throws ClassNotFoundException if a class cannot be found.
*/
private void readObject(final ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
final int rowCount = stream.readInt();
this.data = new Object[rowCount][];
for (int r = 0; r < rowCount; r++) {
final boolean isNotNull = stream.readBoolean();
if (isNotNull) {
final int columnCount = stream.readInt();
final Object[] column = new Object[columnCount];
this.data[r] = column;
for (int c = 0; c < columnCount; c++) {
column[c] = readSerializedData(stream);
}
}
}
}
/**
* Handles the deserialization of a single element of the table.
*
* @param stream the object input stream from which to read the object.
*
* @return the deserialized object
*
* @throws ClassNotFoundException if a class cannot be found.
* @throws IOException Any of the usual Input/Output related exceptions.
*/
protected Object readSerializedData(final ObjectInputStream stream)
throws ClassNotFoundException, IOException {
return stream.readObject();
}
/**
* Clears the table.
*/
public void clear () {
this.rows = 0;
this.columns = 0;
for (int i = 0; i < this.data.length; i++) {
if (this.data[i] != null) {
Arrays.fill(this.data[i], null);
}
}
}
/**
* Copys the contents of the old column to the new column.
*
* @param oldColumn the index of the old (source) column
* @param newColumn the index of the new column
*/
protected void copyColumn (final int oldColumn, final int newColumn)
{
for (int i = 0; i < getRowCount(); i++)
{
setObject(i, newColumn, getObject(i, oldColumn));
}
}
/**
* Copys the contents of the old row to the new row. This uses raw access
* to the data and is remarkably faster than manual copying.
*
* @param oldRow the index of the old row
* @param newRow the index of the new row
*/
protected void copyRow (final int oldRow, final int newRow)
{
this.ensureCapacity(newRow, getColumnCount());
final Object[] oldRowStorage = this.data[oldRow];
if (oldRowStorage == null)
{
final Object[] newRowStorage = this.data[newRow];
if (newRowStorage != null)
{
Arrays.fill(newRowStorage, null);
}
}
else
{
this.data[newRow] = (Object[]) oldRowStorage.clone();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -