/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
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 3 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, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.util;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.Iterator;
import xxl.core.cursors.Cursor;
import xxl.core.cursors.sources.ArrayCursor;
import xxl.core.cursors.sources.Enumerator;
import xxl.core.io.ByteArrayConversions;
import xxl.core.predicates.AbstractPredicate;
import xxl.core.predicates.Predicate;
/**
* The class <code>Arrays</code> contains methods which
* are concerned with arrays of primitive Java types.
*/
public class Arrays {
/**
* This class should never be instantiated
*/
private Arrays() {}
/**
* Returns a new <code>boolean</code> array that is initialized according to
* the parameters. This method is useful especially in
* the relationalNEU package.
*
* @param size size of the array.
* @param initValue value that all boolean values get.
* @return returns a new boolean array
*
*/
public static boolean[] newBooleanArray(int size, boolean initValue) {
boolean[] b = new boolean[size];
java.util.Arrays.fill(b,initValue);
return b;
}
/**
* Returns a new <code>int</code> array that is initialized according to
* the parameters.
*
* @param size size of the array.
* @param initValue value that all int values get.
* @return returns a new int array
*/
public static int[] newIntArray(int size, int initValue) {
int[] i = new int[size];
java.util.Arrays.fill(i,initValue);
return i;
}
/**
* Returns a new <code>byte</code> array that is initialized according to
* the parameters.
*
* @param size size of the array.
* @param byteValue value that all byte values get.
* @return returns a new byte array
*/
public static byte[] newByteArray(int size, byte byteValue) {
byte[] b = new byte[size];
java.util.Arrays.fill(b,byteValue);
return b;
}
/**
* Returns a new <code>char</code> array that is initialized according to
* the parameters.
*
* @param size size of the array.
* @param charValue value that all char values get.
* @return returns a new char array
*/
public static char[] newCharArray(int size, char charValue) {
char[] c = new char[size];
java.util.Arrays.fill(c,charValue);
return c;
}
/**
* Returns a new <code>int</code> array that is initialized according to
* the iterator.
*
* @param size size of the array.
* @param iterator Iterator containing the initialization int-values. The iterator
* should contain exactly <code>size</code> elements. If that is not
* true, then 0s are added (or the rest of the iterator may not be
* traversed).
* @return returns a new int array
*/
public static int[] newIntArray(int size, Iterator iterator) {
int[] i = new int[size];
for (int counter = 0; counter<size ; counter++) {
if (iterator.hasNext())
i[counter] = ((Integer) iterator.next()).intValue();
else
i[counter]=0;
}
return i;
}
/**
* Copies a <code>boolean</code> array and returns the array of size toIndex-fromIndex.
*
* @param array boolean array.
* @param fromIndex the index of the first element (inclusive) to be copied.
* @param toIndex the index of the last element (exclusive) to be copied.
* @return returns a new array created
*/
public static boolean[] copy(boolean[] array,int fromIndex,int toIndex) {
boolean[] array2 = new boolean[toIndex-fromIndex];
for (int i=fromIndex; i<toIndex; i++)
array2[i-fromIndex] = array[i];
return array2;
}
/**
* Copies a <code>byte</code> array and returns the array of size toIndex-fromIndex.
*
* @param array byte array.
* @param fromIndex the index of the first element (inclusive) to be copied.
* @param toIndex the index of the last element (exclusive) to be copied.
* @return returns a new array created
*/
public static byte[] copy(byte[] array,int fromIndex,int toIndex) {
byte[] array2 = new byte[toIndex-fromIndex];
for (int i=fromIndex; i<toIndex; i++)
array2[i-fromIndex] = array[i];
return array2;
}
/**
* Copies an <code>int</code> array and returns the array of size toIndex-fromIndex.
*
* @param array int array.
* @param fromIndex the index of the first element (inclusive) to be copied.
* @param toIndex the index of the last element (exclusive) to be copied.
* @return returns a new array created
*/
public static int[] copy(int[] array,int fromIndex,int toIndex) {
int[] array2 = new int[toIndex-fromIndex];
for (int i=fromIndex; i<toIndex; i++)
array2[i-fromIndex] = array[i];
return array2;
}
/**
* Removes a part of a <code>byte</code> array and returns the resulting
* array. The size of the array depends on the shrink-Parameter.
*
* @param array byte array.
* @param fromIndex the index of the first element (inclusive) to be removed.
* @param toIndex the index of the last element (exclusive) to be removed.
* @param shrink determines if the returned array has length array.length-(toIndex-fromIndex)
* (shrink==true) or array.length (shrink==false).
* @return returns the resulting array
*/
public static byte[] remove(byte[] array, int fromIndex, int toIndex, boolean shrink) {
int dataLength = array.length-(toIndex-fromIndex);
byte[] array2;
if (shrink)
array2 = new byte[dataLength];
else
array2 = new byte[array.length];
for (int i=0; i<fromIndex; i++)
array2[i] = array[i];
for (int i=fromIndex; i<dataLength ; i++)
array2[i] = array[i+(toIndex-fromIndex)];
return array2;
}
/**
* Removes a part of a <code>int</code> array and returns the resulting
* array. The size of the array depends on the shrink-Parameter.
*
* @param array int array.
* @param fromIndex the index of the first element (inclusive) to be removed.
* @param toIndex the index of the last element (exclusive) to be removed.
* @param shrink determines if the returned array has length array.length-(toIndex-fromIndex)
* (shrink==true) or array.length (shrink==false).
* @return returns the resulting array
*/
public static int[] remove(int[] array, int fromIndex, int toIndex, boolean shrink) {
int dataLength = array.length-(toIndex-fromIndex);
int[] array2;
if (shrink)
array2 = new int[dataLength];
else
array2 = new int[array.length];
for (int i=0; i<fromIndex; i++)
array2[i] = array[i];
for (int i=fromIndex; i<dataLength ; i++)
array2[i] = array[i+(toIndex-fromIndex)];
return array2;
}
/**
* Returns a hashcode for a byte array. This mus be efficient, but
* return many different values.
* @param b byte array
* @param offset start of the valid part of the array
* @param size size of the valid part inside the array
* @return a hash code
*/
public static int getHashCodeForByteArray(byte b[], int offset, int size) {
if (size>=5)
return
ByteArrayConversions.convIntLE(b, offset) ^
ByteArrayConversions.convIntLE(b, offset+size-4);
else {
int ret=42;
for (int i=offset; i<offset+size; i++) {
ret <<= 8;
ret = ret | b[i];
}
return ret;
}
}
/**
* Outputs a boolean array to a PrintStream.
*
* @param array boolean array.
* @param out PrintStream to which the representation of the array is written.
*/
public static void print(boolean[] array,PrintStream out) {
out.print("[");
for (int i=0; i<array.length; i++)
out.print(" "+array[i]);
out.print("]");
}
/**
* Outputs an int array to a PrintStream.
*
* @param array int array.
* @param out PrintStream to which the representation of the array is written.
*/
public static void print(int[] array,PrintStream out) {
out.print("[");
for (int i=0; i<array.length; i++)
out.print(" "+array[i]);
out.print("]");
}
/**
* Outputs an Object-array to a PrintStream.
*
* @param array Object array.
* @param out PrintStream to which the representation of the array is written.
*/
public static void print(Object[] array,PrintStream out) {
out.print("[");
for (int i=0; i<array.length; i++)
out.print(" "+array[i]);
out.print("]");
}
/**
* Outputs an Object-array as a line to a PrintStream.
*
* @param array Object array.
* @param out PrintStream to which the representation of the array is written.
* @since 1.1
*/
public static void println(Object[] array,PrintStream out) {
out.print("[ ");
if (array.length>0)
out.print(array[0]);
for (int i=1; i<array.length; i++)
out.print(" , "+array[i]);
out.println(" ]");
}
/**
* Hex chars inside an array.
*/
public static char HEXCHARS[] = new char[]{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/**
* Print the given byte as a hex number to a String.
* @param b byte value
* @return hexadecimal representation
*/
public static String printHex(byte b) {
String res = "";
res += HEXCHARS[((b >> 4) & 0x0F)];
res += HEXCHARS[(b & 0x0F)];
return res;
}
/**
* Print a given 32-bit value (as long) as a hex number to a String.
* @param l long value
* @return hexadecimal representation
*/
public static String printHex(long l) {
StringBuffer res = new StringBuffer();
res.append(HEXCHARS[(int)((l >> 32) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 28) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 24) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 20) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 16) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 12) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 8) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)((l >> 4) & 0x000000000000000F)]);
res.append(HEXCHARS[(int)(l & 0x000000000000000F)]);
return res.toString();
}
/**
* Print the array as a chain of hex numbers the start line number will be zero.
* @param arr byte array
* @param out PrintStream to which the representation of the array is written.
*/
public static void printHexArray(byte[] arr, PrintStream out) {
printHexArray(arr, 0, out);
}
/**
* Print the given byte array as a chain of hex numbers. You can
* specify a line number so that the chain is numbered.
* @param arr byte array
* @param lineNum Number of the first output line.
* @param out PrintStream to which the representation of the array is written.
*/
public static void printHexArray(byte[] arr, long lineNum, PrintStream out) {
for (int i=0; i <= arr.length/16; i++)
{
printHex(lineNum);
out.print("h: ");
for(int j=0; j < 16; j++)
{
if (i*16+j >= arr.length)
return;
printHex(arr[i*16 + j]);
out.print(" ");
}
lineNum += 16;
out.println();
}
}
/**
* Print the array as a chain of hex numbers the start line number will be zero.
* @param arr byte array
* @return hexadecimal representation
*/
public static String printHexArrayString(byte[] arr) {
return printHexArrayString(arr, 0);
}
/**
* Print the given byte array as a chain of hex numbers to a String. You can
* specifie a line number so that the chain is numbered.
* @param arr byte array
* @param lineNum the line numbler
* @return hexadecimal representation
*/
public static String printHexArrayString(byte[] arr, long lineNum) {
StringBuffer result = new StringBuffer();
for (int i=0; i <= arr.length/16; i++)
{
result.append(printHex(lineNum));
result.append("h: ");
for(int j=0; j < 16; j++)
{
if (i*16+j >= arr.length)
return result.toString();
result.append(printHex(arr[i*16 + j]));
result.append(" ");
}
lineNum += 16;
result.append("\n");
}
return result.toString();
}
/**
* The elements from array[0] to array[array.length-1] will be
* returned by this cursor.
* A <code>new Enumerator(array.length)</code> lets
* the elements be returned in the same order as they
* are contained in the given object array.
*
* @param array the object array delivering the elements.
* @return a cursor delivering the elements backed on the given array.
*/
public static Cursor arrayToCursor(Object[] array) {
return new ArrayCursor(array);
}
/**
* The elements from array[begin] to array[end-1] will be
* returned by this cursor.
* A <code>new Enumerator(array.length)</code> lets
* the elements be returned in the same order as they
* are contained in the given object array.
*
* @param array the object array delivering the elements.
* @param begin index to start
* @param end index to stop (exclusive)
* @return a cursor delivering a subset of the elements backed on the given array.
*/
public static Cursor arrayToCursor(Object[] array, int begin, int end) {
return new ArrayCursor(array, new Enumerator(begin, end));
}
/**
* The elements from array[0] to array[array.length-1] will be
* returned by this cursor.
*
* @param array the object array delivering the elements.
* @param indices iterator of indices; the indices of this
* iterator define the order the elements will be returned by
* the cursor.
* @return a cursor delivering the elements backed on the given array and
* the defined order.
*/
public static Cursor arrayToCursor(Object[] array, Iterator indices) {
return new ArrayCursor(array, indices);
}
/**
* Returns an Iterator that iterates on an array of primitive bytes.
*
* @param array input byte array
* @return Iterator iterating over the array
*/
public static Iterator byteArrayIterator(final byte[] array) {
return new Iterator() {
int pos=0;
public boolean hasNext() {
return pos<array.length;
}
public Object next() {
Byte b = new Byte(array[pos]);
pos++;
return b;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an Iterator that iterates on an array of primitive ints.
*
* @param array input int array
* @param size number of elements that are in the iteration.
* @return Iterator iterating over the array
*/
public static Iterator intArrayIterator(final int[] array, final int size) {
return new Iterator() {
int pos=0;
public boolean hasNext() {
return pos<size;
}
public Object next() {
Integer b = new Integer(array[pos]);
pos++;
return b;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an Iterator that iterates on an array of primitive ints.
*
* @param array input int array
* @return Iterator iterating over the array
*/
public static Iterator intArrayIterator(final int[] array) {
return intArrayIterator(array,array.length);
}
/**
* Returns an Iterator that iterates on an array of primitive shorts.
*
* @param array input short array
* @param size number of elements that are in the iteration.
* @return Iterator iterating over the array
*/
public static Iterator shortArrayIterator(final short[] array, final int size) {
return new Iterator() {
int pos=0;
public boolean hasNext() {
return pos<size;
}
public Object next() {
Short b = new Short(array[pos]);
pos++;
return b;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an Iterator that iterates on an array of primitive shorts.
*
* @param array input short array
* @return Iterator iterating over the array
*/
public static Iterator shortArrayIterator(final short[] array) {
return shortArrayIterator(array,array.length);
}
/**
* Returns an Iterator that iterates on an array of primitive longs.
*
* @param array input long array
* @param size number of elements that are in the iteration.
* @return Iterator iterating over the array
*/
public static Iterator longArrayIterator(final long[] array, final int size) {
return new Iterator() {
int pos=0;
public boolean hasNext() {
return pos<size;
}
public Object next() {
Long b = new Long(array[pos]);
pos++;
return b;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an Iterator that iterates on an array of primitive longs.
*
* @param array input long array
* @return Iterator iterating over the array
*/
public static Iterator longArrayIterator(final long[] array) {
return longArrayIterator(array,array.length);
}
/**
* Returns an Iterator that iterates on an array of primitive doubles.
*
* @param array input double array
* @param size number of elements that are in the iteration.
* @return Iterator iterating over the array
*/
public static Iterator doubleArrayIterator(final double[] array, final int size) {
return new Iterator() {
int pos=0;
public boolean hasNext() {
return pos<size;
}
public Object next() {
Double b = new Double(array[pos]);
pos++;
return b;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an Iterator that iterates on an array of primitive doubles.
*
* @param array input double array
* @return Iterator iterating over the array
*/
public static Iterator doubleArrayIterator(final double[] array) {
return doubleArrayIterator(array,array.length);
}
/**
* Returns an Iterator that iterates on an array of Strings.
*
* @param array input String array
* @param size number of elements that are in the iteration.
* @return Iterator iterating over the array
*/
public static Iterator stringArrayIterator(final String[] array, final int size) {
return new Iterator() {
int pos=0;
public boolean hasNext() {
return pos<size;
}
public Object next() {
String b = new String(array[pos]);
pos++;
return b;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Returns an Iterator that iterates on an array of Strings.
*
* @param array input String array
* @return Iterator iterating over the array
*/
public static Iterator stringArrayIterator(final String[] array) {
return stringArrayIterator(array,array.length);
}
/**
* Wrapps a byte array to an outputstream. A call of the write() method on the
* returned outputStream inserts a byte into the array. With every call of the write()
* method the insert-position of enclosed array will be increased by one.
* @param content the byte array
* @param base the position in the array where to start writing
* @param end the position in the array where to stop writing
* @return OutputStream created
*/
public OutputStream byteArrayOutputStream (final byte[] content, final int base, final int end) {
return new OutputStream () {
int position = base;
public void write (int b) throws IOException {
if (position>=end)
throw new IOException();
if (position>=content.length)
throw new IOException();
content[position++] = (byte) b;
}
};
}
/**
* Returns the index in the specified array of the first occurrence
* of the specified element, or -1 if the array does not contain
* this element. More formally, returns the lowest index i such that
* (element == null ? array[i] == null : element.equals(array[i])),
* or -1 if there is no such index.
*
* @param array the array to be searched.
* @param element the element to search for.
* @return the index in the array of the first occurrence of the
* specified element, or -1 if the array does not contain
* this element.
*/
public static int indexOf(Object[] array, Object element) {
for (int i = 0; i < array.length; i++)
if (element == null ? array[i] == null : element.equals(array[i]))
return i;
return -1;
}
/**
* Returns the array index with the smallest element using a given
* comparator.
*
* @param array The array to be searched.
* @param comparator The comparator to compare two elements of the array.
* @return The index in the array of the smallest element or -1 if the
* array does not have elements.
*/
public static int min(Object[] array, Comparator comparator) {
if (array==null || array.length==0)
return -1;
int index=0;
for (int i = 1; i < array.length; i++)
if (comparator.compare(array[i],array[index])<0)
index = i;
return index;
}
/**
* Returns the array index with the biggest element using a given
* comparator.
*
* @param array The array to be searched.
* @param comparator The comparator to compare two elements of the array.
* @return The index in the array of the biggest element or -1 if the
* array does not have elements.
*/
public static int max(Object[] array, Comparator comparator) {
if (array==null || array.length==0)
return -1;
int index=0;
for (int i = 1; i < array.length; i++)
if (comparator.compare(array[i],array[index])>0)
index = i;
return index;
}
/**
* Returns an array containing an ascending sequence of <code>int</code>
* values within the specified range [<code>from</code>;<code>to</code>].
*
* @param from the start of the returned <code>int</code> value sequence
* (inclusive).
* @param to the end of the returned <code>int</code> value sequence
* (exclusive).
* @return an array containing an ascending sequence of <code>int</code>
* values within the specified range
* [<code>from</code>;<code>to</code>].
*/
public static int[] enumeratedIntArray(int from, int to) {
int[] array = new int[to - from];
for (int i = 0, v = from; v < to; array[i++] = v++);
return array;
}
/**
* Increments every column of the given array by the given increment and
* returns it.
*
* @param array the array holding the <code>int</code> values to be
* incremented.
* @param increment the value the array's columns are increased by.
* @return an array containing the incremented values of the given array.
*/
public static int[] incrementIntArray(int[] array, int increment) {
int[] inc = new int[array.length];
for (int i = 0; i < array.length; inc[i] = array[i++]+increment);
return inc;
}
/**
* Decrements every column of the given array by the given decrement and
* returns it.
*
* @param array the array holding the <code>int</code> values to be
* decremented.
* @param decrement the value the array's columns are decreased by.
* @return an array containing the decremented values of the given array.
*/
public static int[] decrementIntArray(int[] array, int decrement) {
return incrementIntArray(array, -decrement);
}
public static <I> Predicate<I[]> typedArrayEquals() {
return new AbstractPredicate<I[]>() {
@Override
public boolean invoke(I[] a1, I[] a2) {
if (a1==null || a2==null) {
if (a1==null && a2==null)
return true;
return false;
}
if (a1.length != a2.length)
return false;
for (int i=0; i<a1.length; i++) {
if (a1[i]==null || a2[i]==null) {
if (a1[i]==null && a2[i]==null)
continue;
return false;
}
if (!a1[i].equals(a2[i]))
return false;
}
return true;
}
};
}
}