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(arr1, 0, arr2);
Array.set(arr1, 1, arr3);
その場合、arr1は次と同等の2D配列になります。
String[2][4] arr1;
これはどうですか?実行時までこの配列の次元がわからない場合はどうなりますか?
編集:これが役立つ場合(私はそれが役立つと確信しています...)私たちはフォームの文字列から未知の次元の配列を解析しようとしています
[value1, value2, ...]
または
[ [value11, value12, ...] [value21, value22, ...] ...]
等々
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);
等々。オブジェクトの巨大なネストされた配列である必要があります
実際には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));
}
}
Creating array with dimensions / sizes: [2][3][2]
[[[pos 000, pos 001], [pos 010, pos 011], [pos 020, pos 021]],
[[pos 100, pos 101], [pos 110, pos 111], [pos 120, pos 121]]]
配列はJava-単純な配列と「多次元」配列(つまり、配列の配列)に適用されます)でタイプセーフです。
ネストの深さが実行時に可変である場合、実行できる最善の方法は、既知の最小ネスト深度(おそらく1)に対応する配列を使用することです。この配列の要素は、単純な要素であるか、さらにネストする場合に使用します。別の配列が必要です。ネストされた配列自体もオブジェクトと見なされ、型システム内に収まるため、Object []配列を使用するとこれを実行できます。
ネストが完全に規則的である場合は、Array.newInstance(String.class, dimension1, dimension2, ...)
を使用して、この規則性をプリエンプトし、適切な多次元配列を作成できます。ネストが不規則な場合は、「ギザギザ」を許容するネストされたリストを使用することをお勧めします。構造と動的サイジング。ジェネリックスを犠牲にして、ギザギザの構造を持つことができます。一部の要素は単純なアイテムであり、他の要素はさらにネストされたリストである可能性があるため、構造がギザギザになっている場合、ジェネリックは使用できません。
したがって、複数のディメンションをArray.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]
もう1つのオプションは、前のレベルの配列の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("]");
}
}
配列の次元がわからない場合は、次の方法は機能しません。ただし、寸法がわかっている場合は、反射を使用しないでください。以下をせよ:
それよりもはるかに簡単に2D配列を動的に構築できます。
int x = //some value
int y = //some other value
String[][] arr = new String[x][y];
これにより、「動的に」x
by y
2d配列が作成されます。
さらに、次のようなことを試してみるとどうなるでしょうか。
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); ...
いいえ、そのようなString[]
値を設定することはできません。あなたは遭遇します
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 item#(覚えていない):ライブラリを知って使用してください。
List
とtoArray
メソッドを使用できます。
List<String[]> twoDimension = new ArrayList<String[]>();
それを配列に変換するには、次を使用します。
String [][] theArray = twoDimension.toArray( new String[twoDimension.size()][] );
秘訣は、外側の配列がString[]
(文字列配列)を保持するように宣言されていることです。これは、別のList<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()][]);
そこ。これで、result
は、予想どおり[[1], [2, 3], [4, 5, 6, 7], [8, 9, 10, 11, 12, 13]]
を含む動的に作成された2次元の配列になります。
これが 完全な実行デモ です。これはまた、空白を排除するために、ミックスに正規表現を追加します。
他のシナリオを処理させます。
そこで、変数の数が可変の多項式から係数を抽出するコードでこの質問に出くわしました。したがって、ユーザーは2つの変数_3 x^2 + 2 x y
_の多項式の係数配列が必要な場合もあれば、3つの変数を持つ1つの場合もあります。理想的には、ユーザーが簡単に問い合わせることができ、Integer []、Integer [] []などにキャストできる多次元配列が必要です。
これは基本的に、Array.newInstance(obj.getClass(), size)
メソッドを使用して、jdmichalの回答と同じ手法を使用します。多次元配列の場合、objは1次元少ない配列にすることができます。
ランダムに作成された要素を含むサンプルコード
_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));
}
}
_