可以用Java动态构建多维数组吗?
假设我们有Java代码:可以用Java动态构建多维数组吗?,java,arrays,dynamic,multidimensional-array,Java,Arrays,Dynamic,Multidimensional Array,假设我们有Java代码: Object arr = Array.newInstance(Array.class, 5); 那会跑吗?作为进一步说明,如果我们尝试这样的方法会怎么样: Object arr1 = Array.newInstance(Array.class, 2); Object arr2 = Array.newInstance(String.class, 4); Object arr3 = Array.newInstance(String.class, 4); Array.set
Object arr = Array.newInstance(Array.class, 5);
那会跑吗?作为进一步说明,如果我们尝试这样的方法会怎么样:
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
Array.set(arr1, 1, arr3);
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
...
那么arr1是否是一个2D数组,相当于:
String[2][4] arr1;
这样如何:如果我们在运行时之前不知道这个数组的维度呢
编辑:如果这有帮助的话(我肯定会…),我们正试图从表单的字符串中解析未知维度的数组
[value1, value2, ...]
或
等等
Edit2:如果像我这样愚蠢的人尝试这种垃圾软件,这里有一个至少可以编译和运行的版本。逻辑是否合理完全是另一个问题
Object arr1 = Array.newInstance(Object.class, x);
Object arr11 = Array.newInstance(Object.class, y);
Object arr12 = Array.newInstance(Object.class, y);
...
Object arr1x = Array.newInstance(Object.class, y);
Array.set(arr1, 0, arr11);
Array.set(arr1, 1, arr12);
...
Array.set(arr1, x-1, arr1x);
等等。它必须是一个巨大的嵌套对象数组好的,如果您不确定数组的尺寸,那么下面的方法将不起作用。但是,如果您确实知道尺寸,请不要使用反射。请执行以下操作: 您可以更轻松地动态构建二维阵列
int x = //some value
int y = //some other value
String[][] arr = new String[x][y];
这将通过y
2d数组“动态”创建x
作为进一步说明,如果我们尝试这样的方法会怎么样:
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
Array.set(arr1, 1, arr3);
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
...
不,您不能这样设置字符串[]
值。你遇到
Exception in thread "main" java.lang.IllegalArgumentException: array element type mismatch
at java.lang.reflect.Array.set(Native Method)
at Test.main(Test.java:12)
数组在java中是类型安全的,适用于简单数组和“多维”数组,即数组的数组 如果嵌套深度在运行时是可变的,那么最好使用与已知最小嵌套深度(假定为1)相对应的数组。此数组中的元素可以是简单元素,或者如果需要进一步嵌套,则使用另一个数组。Object[]数组允许您这样做,因为嵌套数组本身也被视为对象,因此适合于类型系统
如果嵌套是完全规则的,那么您可以使用
array.newInstance(String.class,dimension1,dimension2,…)
抢先使用此规则并创建适当的多维数组。如果嵌套是不规则的,您最好使用嵌套列表,它允许“锯齿”结构和动态大小调整。你可以有一个锯齿状的结构,以泛型为代价。如果结构参差不齐,则不能使用泛型,因为某些元素可能是简单项,而其他元素可能是进一步嵌套的列表。因此可以将多个维度传递给数组。newInstance
,但这会强制每个维度具有固定长度。如果可以,您可以使用以下选项:
// We already know from scanning the input that we need a 2 x 4 array.
// Obviously this array would be created some other way. Probably through
// a List.toArray operation.
final int[] dimensions = new int[2];
dimensions[0] = 2;
dimensions[1] = 4;
// Create the array, giving the dimensions as the second input.
Object array = Array.newInstance(String.class, dimensions);
// At this point, array is a String[2][4].
// It looks like this, when the first dimension is output:
// [[Ljava.lang.String;@3e25a5, [Ljava.lang.String;@19821f]
//
// The second dimensions look like this:
// [null, null, null, null]
另一个选项是从底部构建它们,使用上一级数组上的getClass
作为下一级数组的输入。以下代码运行并生成由节点定义的锯齿状数组:
import java.lang.reflect.Array;
public class DynamicArrayTest
{
private static class Node
{
public java.util.List<Node> children = new java.util.LinkedList<Node>();
public int length = 0;
}
public static void main(String[] args)
{
Node node1 = new Node();
node1.length = 1;
Node node2 = new Node();
node2.length = 2;
Node node3 = new Node();
node3.length = 3;
Node node4 = new Node();
node4.children.add(node1);
node4.children.add(node2);
Node node5 = new Node();
node5.children.add(node3);
Node node6 = new Node();
node6.children.add(node4);
node6.children.add(node5);
Object array = createArray(String.class, node6);
outputArray(array); System.out.println();
}
private static Object createArray(Class<?> type, Node root)
{
if (root.length != 0)
{
return Array.newInstance(type, root.length);
}
else
{
java.util.List<Object> children = new java.util.ArrayList<Object>(root.children.size());
for(Node child : root.children)
{
children.add(createArray(type, child));
}
Object array = Array.newInstance(children.get(0).getClass(), children.size());
for(int i = 0; i < Array.getLength(array); ++i)
{
Array.set(array, i, children.get(i));
}
return array;
}
}
private static void outputArray(Object array)
{
System.out.print("[ ");
for(int i = 0; i < Array.getLength(array); ++i)
{
Object element = Array.get(array, i);
if (element != null && element.getClass().isArray())
outputArray(element);
else
System.out.print(element);
System.out.print(", ");
}
System.out.print("]");
}
}
import java.lang.reflect.Array;
公共类动态测试
{
私有静态类节点
{
public java.util.List children=new java.util.LinkedList();
公共整数长度=0;
}
公共静态void main(字符串[]args)
{
Node node1=新节点();
node1.length=1;
Node node2=新节点();
node2.length=2;
Node node3=新节点();
节点3.长度=3;
Node node4=新节点();
node4.children.add(node1);
node4.children.add(node2);
Node node5=新节点();
node5.children.add(node3);
Node node6=新节点();
node6.children.add(node4);
node6.children.add(node5);
对象数组=createArray(String.class,node6);
outputArray(数组);System.out.println();
}
私有静态对象createArray(类类型,节点根)
{
如果(root.length!=0)
{
返回Array.newInstance(类型,root.length);
}
其他的
{
java.util.List children=new java.util.ArrayList(root.children.size());
for(节点子节点:root.children)
{
add(createArray(type,child));
}
Object array=array.newInstance(children.get(0.getClass(),children.size());
对于(int i=0;i
实际上,在java中这样做是可能的。(我必须说,我有点惊讶。)
免责声明;除了作为这个问题的答案之外,我从来都不想在任何地方看到这个代码。我强烈建议您使用List
s
import java.lang.reflect.Array;
import java.util.*;
public class Test {
public static int[] tail(int[] arr) {
return Arrays.copyOfRange(arr, 1, arr.length);
}
public static void setValue(Object array, String value, int... indecies) {
if (indecies.length == 1)
((String[]) array)[indecies[0]] = value;
else
setValue(Array.get(array, indecies[0]), value, tail(indecies));
}
public static void fillWithSomeValues(Object array, String v, int... sizes) {
for (int i = 0; i < sizes[0]; i++)
if (sizes.length == 1)
((String[]) array)[i] = v + i;
else
fillWithSomeValues(Array.get(array, i), v + i, tail(sizes));
}
public static void main(String[] args) {
// Randomly choose number of dimensions (1, 2 or 3) at runtime.
Random r = new Random();
int dims = 1 + r.nextInt(3);
// Randomly choose array lengths (1, 2 or 3) at runtime.
int[] sizes = new int[dims];
for (int i = 0; i < sizes.length; i++)
sizes[i] = 1 + r.nextInt(3);
// Create array
System.out.println("Creating array with dimensions / sizes: " +
Arrays.toString(sizes).replaceAll(", ", "]["));
Object multiDimArray = Array.newInstance(String.class, sizes);
// Fill with some
fillWithSomeValues(multiDimArray, "pos ", sizes);
System.out.println(Arrays.deepToString((Object[]) multiDimArray));
}
}
有效的Java项目#(我不记得了):了解并使用库
您可以使用列表
和toArray
方法:
List<String[]> twoDimension = new ArrayList<String[]>();
诀窍是,外部数组被声明为保存String[]
(字符串数组),然后可以使用另一个列表
动态创建该数组,或者,如果您正在使用String.split
方法解析字符串,则可以动态创建该数组
演示
着重于数组的动态创建,而不是解析,下面是一个与String.split结合使用的示例
// and array which contains N elements of M size
String input = "[[1],[2,3],[4,5,6,7],[8,9,10,11,12,13]]";
// Declare your dynamic array
List<String[]> multiDimArray = new ArrayList<String[]>();
// split where ],[ is found, just ignore the leading [[ and the trailing ]]
String [] parts = input.replaceAll("\\[\\[|\\]\\]","")
.split("\\],\\[");
// now split by comma and add it to the list
for( String s : parts ){
multiDimArray.add( s.split(",") ) ;
}
String [][] result = multiDimArray.toArray( new String[multiDimArray.size()][]);
//和包含N个大小为M的元素的数组
字符串输入=“[1],[2,3],[4,5,6,7],[8,9,10,11,12,13]”;
//声明动态数组
List multiDimArray=新建ArrayList();
//在找到“,”的地方拆分,只需忽略前导[[和尾随]]
String[]parts=input.replaceAll(“\\[\\[\\\[\\\]\\\]]”,“”)
.split(“\\]”,\\[”;
//现在按逗号拆分并将其添加到列表中
用于(字符串s:零件){
multiDimArray.add(s.split(“,”);
}
字符串[][]结果
// and array which contains N elements of M size
String input = "[[1],[2,3],[4,5,6,7],[8,9,10,11,12,13]]";
// Declare your dynamic array
List<String[]> multiDimArray = new ArrayList<String[]>();
// split where ],[ is found, just ignore the leading [[ and the trailing ]]
String [] parts = input.replaceAll("\\[\\[|\\]\\]","")
.split("\\],\\[");
// now split by comma and add it to the list
for( String s : parts ){
multiDimArray.add( s.split(",") ) ;
}
String [][] result = multiDimArray.toArray( new String[multiDimArray.size()][]);
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;
public class MultiDimArray {
static Random rand = new Random();
/**
* Create an multi-dimensional array
* @param depth number of dimensions
* @return
*/
static Object buildArray(int depth) {
if(depth ==1) { // For 1D case just use a normal array
int size = rand.nextInt(3)+1;
Integer[] res = new Integer[size];
for(int i=0;i<size;++i) {
res[i] = new Integer(i);
}
return res;
}
// 2 or more dimensions, using recursion
int size = rand.nextInt(3)+1;
// Need to get first items so can find its class
Object ele0 = buildArray(depth-1);
// create array of correct type
Object res = Array.newInstance(ele0.getClass(), size);
Array.set(res, 0, ele0);
for(int i=1;i<size;++i) {
Array.set(res, i, buildArray(depth-1));
}
return res;
}
public static void main(String[] args) {
Integer[] oneD = (Integer[]) buildArray(1);
System.out.println(Arrays.deepToString(oneD));
Integer[][] twoD = (Integer[][]) buildArray(2);
System.out.println(Arrays.deepToString(twoD));
Integer[][][] threeD = (Integer[][][]) buildArray(3);
System.out.println(Arrays.deepToString(threeD));
}
}