Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.organicdesign.fp.collections.Cowry Maven / Gradle / Ivy
package org.organicdesign.fp.collections;
import java.lang.reflect.Array;
import java.util.Arrays;
import org.organicdesign.fp.tuple.Tuple2;
/**
Cowry is short for Copy On Write aRraY and contains utilities for doing this quickly and correctly.
It's package-private for now, final, and cannot be instantiated.
Created by gpeterso on 5/21/17.
*/
final class Cowry {
private Cowry() {
throw new UnsupportedOperationException("Do not instantiate");
}
// We only one empty array and it makes the code simpler than pointing to null all the time.
// Have to time the difference between using this and null. The only difference I can imagine
// is that this has an address in memory and null does not, so it could save a memory lookup
// in some places.
static final Object[] EMPTY_ARRAY = new Object[0];
// =================================== Array Helper Functions ==================================
// Helper function to avoid type warnings.
@SuppressWarnings("unchecked")
static T[] emptyArray() { return (T[]) EMPTY_ARRAY; }
// // Thank you jeannicolas
// // http://stackoverflow.com/questions/80476/how-can-i-concatenate-two-arrays-in-java
// private static T[] arrayGenericConcat(T[] a, T[] b) {
// int aLen = a.length;
// int bLen = b.length;
//
// @SuppressWarnings("unchecked")
// T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
// System.arraycopy(a, 0, c, 0, aLen);
// System.arraycopy(b, 0, c, aLen, bLen);
//
// return c;
// }
// Helper function to avoid type warnings.
@SuppressWarnings("unchecked")
static T[] singleElementArray(T elem) { return (T[]) new Object[] { elem }; }
// Helper function to avoid type warnings.
@SuppressWarnings("unchecked")
static T[] singleElementArray(T elem, Class tClass) {
if (tClass == null) {
return (T[]) new Object[] { elem };
}
T[] newItems = (T[]) Array.newInstance(tClass, 1);
newItems[0] = elem;
return newItems;
}
static T[] insertIntoArrayAt(T item, T[] items, int idx, Class tClass) {
// Make an array that's one bigger. It's too bad that the JVM bothers to
// initialize this with nulls.
@SuppressWarnings("unchecked")
// Make an array that big enough. It's too bad that the JVM bothers to
// initialize this with nulls.
T[] newItems = (T[]) ((tClass == null) ? new Object[items.length + 1]
: Array.newInstance(tClass, items.length + 1) );
// If we aren't inserting at the first item, array-copy the items before the insert
// point.
if (idx > 0) {
System.arraycopy(items, 0, newItems, 0, idx);
}
// Insert the new item.
newItems[idx] = item;
// If we aren't inserting at the last item, array-copy the items after the insert
// point.
if (idx < items.length) {
System.arraycopy(items, idx, newItems, idx + 1, items.length - idx);
}
return newItems;
}
static T[] arrayCopy(T[] items, int length, Class tClass) {
@SuppressWarnings("unchecked")
T[] newItems = (T[]) ((tClass == null) ? new Object[length]
: Array.newInstance(tClass, length) );
System.arraycopy(items, 0, newItems, 0,
items.length < length ? items.length
: length);
return newItems;
}
// private static T[] insertIntoArrayAt(T item, T[] items, int idx) {
// return insertIntoArrayAt(item, items, idx, null);
// }
/**
Called splice, but handles precat (idx = 0) and concat (idx = origItems.length).
@param insertedItems the items to insert
@param origItems the original items.
@param idx the index to insert new items at
@param tClass the class of the resulting new array
@return a new array with the new items inserted at the proper position of the old array.
*/
static A[] spliceIntoArrayAt(A[] insertedItems, A[] origItems, int idx,
Class tClass) {
// Make an array that big enough. It's too bad that the JVM bothers to
// initialize this with nulls.
@SuppressWarnings("unchecked")
A[] newItems = tClass == null ? (A[]) new Object[insertedItems.length + origItems.length] :
(A[]) Array.newInstance(tClass, insertedItems.length + origItems.length);
// If we aren't inserting at the first item, array-copy the items before the insert
// point.
if (idx > 0) {
// src, srcPos, dest,destPos,length
System.arraycopy(origItems, 0, newItems, 0, idx);
}
// Insert the new items
// src, srcPos, dest, destPos, length
System.arraycopy(insertedItems, 0, newItems, idx, insertedItems.length);
// If we aren't inserting at the last item, array-copy the items after the insert
// point.
if (idx < origItems.length) {
System.arraycopy(origItems, idx, newItems, idx + insertedItems.length,
origItems.length - idx);
}
return newItems;
}
// private static int[] replaceInIntArrayAt(int replacedItem, int[] origItems, int idx) {
// // Make an array that big enough. It's too bad that the JVM bothers to
// // initialize this with nulls.
// int[] newItems = new int[origItems.length];
// System.arraycopy(origItems, 0, newItems, 0, origItems.length);
// newItems[idx] = replacedItem;
// return newItems;
// }
@SuppressWarnings("unchecked")
static T[] replaceInArrayAt(T replacedItem, T[] origItems, int idx,
Class tClass) {
// Make an array that big enough. It's too bad that the JVM bothers to
// initialize this with nulls.
T[] newItems = (T[]) ( (tClass == null) ? new Object[origItems.length]
: Array.newInstance(tClass, origItems.length) );
System.arraycopy(origItems, 0, newItems, 0, origItems.length);
newItems[idx] = replacedItem;
return newItems;
}
/**
Only call this if the array actually needs to be split (0 < splitPoint < orig.length).
@param orig array to split
@param splitIndex items less than this index go in the left, equal or greater in the right.
@return a 2D array of leftItems then rightItems
*/
static Tuple2 splitArray(T[] orig, int splitIndex) { //, Class tClass) {
// if (splitIndex < 1) {
// throw new IllegalArgumentException("Called split when splitIndex < 1");
// }
// if (splitIndex > orig.length - 1) {
// throw new IllegalArgumentException("Called split when splitIndex > orig.length - 1");
// }
// NOTE:
// I sort of suspect that generic 2D array creation where the two arrays are of a different
// length is not possible in Java, or if it is, it's not likely to be much faster than
// what we have here. I'd just copy the Arrays.copyOf code everywhere this function is used
// if you want more speed.
// int rightLength = orig.length - splitIndex;
// Class tClass = (Class) orig.getClass().getComponentType();
// Tuple2 split = Tuple2.of((T[]) Array.newInstance(tClass, splitIndex),
// (T[]) Array.newInstance(tClass, rightLength));
//
// Tuple2 split =
return Tuple2.of(Arrays.copyOf(orig, splitIndex),
Arrays.copyOfRange(orig, splitIndex, orig.length));
// // original array, offset, newArray, offset, length
// System.arraycopy(orig, 0, split._1(), 0, splitIndex);
//
// System.arraycopy(orig, splitIndex, split._2(), 0, rightLength);
// return split;
}
/**
Only call this if the array actually needs to be split (0 < splitPoint < orig.length).
@param orig array to split
@param splitIndex items less than this index go in the left, equal or greater in the right.
@return a 2D array of leftItems then rightItems
*/
static int[][] splitArray(int[] orig, int splitIndex) {
// This function started an exact duplicate of the one above, but for ints.
// if (splitIndex < 1) {
// throw new IllegalArgumentException("Called split when splitIndex < 1");
// }
// if (splitIndex > orig.length - 1) {
// throw new IllegalArgumentException("Called split when splitIndex > orig.length - 1");
// }
int rightLength = orig.length - splitIndex;
int[][] split = new int[][] {new int[splitIndex],
new int[rightLength]};
// original array, offset, newArray, offset, length
System.arraycopy(orig, 0, split[0], 0, splitIndex);
System.arraycopy(orig, splitIndex, split[1], 0, rightLength);
return split;
}
// static T[] truncateArray(T[] origItems, int newLength, Class tClass) {
// if (origItems.length == newLength) {
// return origItems;
// }
//
// @SuppressWarnings("unchecked")
// T[] newItems = (T[]) ((tClass == null) ? new Object[newLength]
// : Array.newInstance(tClass, newLength) );
//
// // src, srcPos, dest,destPos, length
// System.arraycopy(origItems, 0, newItems, 0, newLength);
// return newItems;
// }
}