[英]Copy jagged n-dimensional primitive array to new type in java
我覺得我可能缺少一些明顯的東西。 我需要將Java中的鋸齒狀n維數組從一個復制到另一個原始(數字)類型(例如,從double [] [] [] []到int [] [] [] [])。 我下面的代碼使用Object [] s工作。 我如何(或“我什至可以”)生成一種新型的n維基本數組? (“鋸齒狀”是指同一級別的某些數組可能具有與示例數據中不同的維度)。 任何幫助表示贊賞。
public class ArrayToNewType {
public static void main(String... args) {
Object loNew = arrayAsNewType(
new double[][][][]
{
array1,
array2,
array2Nulls,
array3a
},
int.class);
}
public static Object arrayAsNewType(Object pArray,
Class<?> pNewType)
{
Object[] lNewArray
= new Object[java.lang.reflect.Array.getLength(pArray)];
deepCopy(pArray,
lNewArray,
pNewType);
return lNewArray;
}
private static void deepCopy(Object pOriginal,
Object pCopy,
Class<?> pNewType) {
if (pOriginal == null || !pOriginal.getClass().isArray()) {
return;
}
for (int liIndex = 0;
liIndex < java.lang.reflect.Array.getLength(pOriginal);
liIndex++) {
Object lElement = java.lang.reflect.Array.get(pOriginal,
liIndex);
if (lElement.getClass().isArray()) {
int liElementLength =
java.lang.reflect.Array.getLength(lElement);
java.lang.reflect.Array.set(
pCopy,
liIndex,
!lElement.getClass().getComponentType().isArray()
? java.lang.reflect.Array.newInstance(
pNewType,
liElementLength)
: new Object[liElementLength]);
}
else {
java.lang.reflect.Array.set(pCopy,
liIndex,
castToPrimitive(lElement,
pNewType));
}
deepCopy(lElement,
java.lang.reflect.Array.get(pCopy,
liIndex),
pNewType);
}
}
// Sample data
static double[][][] array1 =
{
{{3D, 4D, 5D, 2D, 13D}, {8D}, {28D}},
{{8D}, {4228.2D, 4D, -.29D, 3D}, {228D}},
{{48D}, {228D}},
{{48D}, {28D}}
};
static double[][][] array2 =
{
{{8}, {3, 4, 5, 2, 3}, {28}},
{{8}, {4228, 4, 29, 3}, {228}},
{{248}, {228}},
{{0}, {-2899}, {9}}
};
static double[][][] array2Nulls =
{
{{8}, {3, 4, 5, 2, 3}, {28}},
{{8}, {4228, 4, 29, 3}, {228}},
{},
{{0}, {-2899}, {9}}
};
static double[][][] array3a =
{
{{8D}, {554D, 5D, 2D, 3D}, {28D}},
{{48D}, {228D}},
{{48D}, {328.65D}}
};
static <T extends Number> Object castToPrimitive(Object pElement,
Class<?> pNewType)
{
if (pNewType.equals(byte.class)) {
return ((Number) pElement).byteValue();
}
if (pNewType.equals(short.class)) {
return ((Number) pElement).shortValue();
}
if (pNewType.equals(int.class)) {
return ((Number) pElement).intValue();
}
if (pNewType.equals(long.class)) {
return ((Number) pElement).longValue();
}
if (pNewType.equals(double.class)) {
return ((Number) pElement).doubleValue();
}
if (pNewType.equals(float.class)) {
return ((Number) pElement).floatValue();
}
return (pElement);
}
}
另一種使用反射但直接使用原始類型的方法:
import java.lang.reflect.Array;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class NdArrayCaster {
private final static Map<Class<?>, NumberClassWrapper> TYPES = new HashMap<Class<?>, NumberClassWrapper>() {
{
put(byte.class, new ByteClassWrapper());
put(short.class, new ShortClassWrapper());
put(int.class, new IntClassWrapper());
put(long.class, new LongClassWrapper());
put(float.class, new FloatClassWrapper());
put(double.class, new DoubleClassWrapper());
}
};
/**
* Returns a "deep casted" copy of ndArray with the given base type.
*/
public static Object cast(Object ndArray, Class<?> baseTypeClass) {
checkThatPrimitiveArray(ndArray);
int dimension = getDimension(ndArray);
NumberClassWrapper wrapper = TYPES.get(baseTypeClass);
return cast(ndArray, wrapper, dimension);
}
/**
* Throws an IllegalArgumentException if ndArray is not a primitive type array.
*/
private static void checkThatPrimitiveArray(Object ndArray) {
if (!ndArray.getClass().getName().matches("\\[*[BSIJFD]")) {
throw new IllegalArgumentException("ndArray is not a primitive array.");
}
}
/**
* Returns the array's dimension.
*/
private static int getDimension(Object ndArray) {
return ndArray.getClass().getName().length() - 1;
}
/**
* Casts an old to an array of the given type and dimension.
* <p>
* This is called recursive for each dimension.
*/
private static Object cast(Object old, NumberClassWrapper wrapper, int dimension) {
if (dimension == 0) {
return wrapper.cast((Number) old);
}
int size = Array.getLength(old);
Object newArray = wrapper.createArray(dimension, size);
for (int i = 0; i < size; i++) {
Object child = Array.get(old, i);
Array.set(newArray, i, cast(child, wrapper, dimension - 1));
}
return newArray;
}
/**
* Class providing information for a primitive type.
*/
private static abstract class NumberClassWrapper<N extends Number> {
private final Class<N> primitiveClass;
private final String jvmName;
NumberClassWrapper(Class<N> numberClass, String jvmName) {
this.primitiveClass = numberClass;
this.jvmName = jvmName;
}
/**
* Casts a number to the type represented by this Wrapper.
*/
abstract N cast(Number value);
/**
* Creates a primitive array with the given dimension and the given size at the lowest dimension.
* <p>
* Example: `IntClassWrapper.createArray(3,4)` returns the same as `new int[4][][]`.
*/
final Object createArray(int dimension, int size) {
return Array.newInstance(getBaseClassForArrayCreation(dimension), size);
}
Class getBaseClassForArrayCreation(int dimension) {
if (dimension == 1) {
return primitiveClass;
} else {
try {
return Class.forName(getArrayJVMName(dimension - 1));
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new Error("Cannot happen.");
}
}
}
/**
* Returns the JVM name of the corresponding primitive array with the given dimension.
*/
private String getArrayJVMName(int dimension) {
return String.join("", Collections.nCopies(dimension, "[")) + jvmName;
}
}
private final static class ByteClassWrapper extends NumberClassWrapper<Byte> {
ByteClassWrapper() {
super(byte.class, "B");
}
@Override
public Byte cast(Number n) {
return n.byteValue();
}
}
private final static class ShortClassWrapper extends NumberClassWrapper<Short> {
ShortClassWrapper() {
super(short.class, "S");
}
@Override
Short cast(Number n) {
return n.shortValue();
}
}
private final static class IntClassWrapper extends NumberClassWrapper<Integer> {
IntClassWrapper() {
super(int.class, "I");
}
@Override
Integer cast(Number n) {
return n.intValue();
}
}
private final static class LongClassWrapper extends NumberClassWrapper<Long> {
LongClassWrapper() {
super(long.class, "J");
}
@Override
Long cast(Number n) {
return n.longValue();
}
}
private final static class FloatClassWrapper extends NumberClassWrapper<Float> {
FloatClassWrapper() {
super(float.class, "F");
}
@Override
Float cast(Number n) {
return n.floatValue();
}
}
private final static class DoubleClassWrapper extends NumberClassWrapper<Double> {
DoubleClassWrapper() {
super(double.class, "D");
}
@Override
Double cast(Number n) {
return n.doubleValue();
}
}
public static void main(String... args) {
// Sample data
double[][][] array1 = {
{{3D, 4D, 5D, 2D, 13D}, {8D}, {28D}},
{{8D}, {4228.2D, 4D, -.29D, 3D}, {228D}},
{{48D}, {228D}},
{{48D}, {28D}}
};
double[][][] array2 = {
{{8}, {3, 4, 5, 2, 3}, {28}},
{{8}, {4228, 4, 29, 3}, {228}},
{{248}, {228}},
{{0}, {-2899}, {9}}
};
double[][][] array2Nulls = {
{{8}, {3, 4, 5, 2, 3}, {28}},
{{8}, {4228, 4, 29, 3}, {228}},
{},
{{0}, {-2899}, {9}}
};
double[][][] array3a = {
{{8D}, {554D, 5D, 2D, 3D}, {28D}},
{{48D}, {228D}},
{{48D}, {328.65D}}
};
double[][][][] ndArray = {array1, array2, array2Nulls, array3a};
System.out.println(cast(ndArray, byte.class).getClass());
System.out.println(cast(ndArray, short.class).getClass());
System.out.println(cast(ndArray, int.class).getClass());
System.out.println(cast(ndArray, long.class).getClass());
System.out.println(cast(ndArray, float.class).getClass());
System.out.println(cast(ndArray, double.class).getClass());
Object[] objectArray = new Object[]{new Object()};
try {
System.out.println(cast(objectArray, byte.class).getClass());
} catch (IllegalArgumentException e) {
System.out.println("Object array not working: check.");
}
try {
System.out.println(cast(new Object(), byte.class).getClass());
} catch (IllegalArgumentException e) {
System.out.println("Object not working: check.");
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.