JAVA 配列とコンテナ クラスの間には、効率、型、基本型を保存する機能という 3 つの主な違いがあります。 JAVA では、配列はオブジェクト参照のシーケンスを格納し、ランダムにアクセスする最も効率的な方法です。配列は単純な線形シーケンスであるため、要素へのアクセスが非常に高速になります。ただし、その代償として、配列のサイズは固定されており、その存続期間中は変更できません。
ジェネリックスと自動パッケージ化メカニズムのおかげで、コンテナーは配列とほぼ同じくらい簡単にプリミティブ型で使用できるようになりました。配列とコンテナーはどちらも、範囲外になると、RuntimeException が発生するため、それらの悪用をある程度防ぐことができます。配列の唯一の利点は効率性です。ただし、より一般的な問題を解決したい場合、配列では制約が多すぎる可能性があるため、この場合でもほとんどの人はコンテナーを選択します。
したがって、最新の JAVA バージョンを使用している場合は、配列よりもコンテナーを選択する必要があります。プログラムを配列にリファクタリングするのは、パフォーマンスに問題があることが判明し、配列に切り替えることでパフォーマンスが向上する場合にのみ行う必要があります。
【初期化】
JAVA には配列の初期化に関して非常に厳格な規制があり、配列の悪用を効果的に防止できます。初期化エラーが発生した場合は、RuntimeException ではなく CompileException が直接発生します。配列が適切に初期化されるまで、この配列参照では何も実行できません。
配列定義には、int[] array と int array[] が含まれます。通常、最初のスタイルは型と変数名を分離するために使用されます。
配列を初期化するには、静的初期化と動的初期化の 2 つの方法があります。長さは初期化時に指定する必要があり、多次元配列の最初の次元の長さを指定する必要があり、高次元から低次元まで定義する必要があります。初期化アクションはコード内のどこにでも指定できますが、{} メソッドは配列が作成される場所にのみ指定できます。特定の初期化方法については、プログラムを参照してください。
arrayA = new int[10] //動的初期化
System.out.println("配列Aの長さ: " + 配列A.長さ);
int[] arrayC = 新しい int[]{1,2,3,4};
System.out.println("配列Cの長さ: " + 配列C.長さ);
//int[] arrayD = new int[1]{1}; //間違った初期化、次元と初期化値を同時に定義することはできません
int[][] arrayE = 新しい int[1][];
System.out.println("配列Eの長さ: " + 配列E.長さ);
//int[][] arrayF = new int[][2] //高次元の長さを最初に指定する必要があります
int[][] arrayG = new int[][]{{1,2,3,4},{5,6,7},{7,24,23,24}};
System.out.println("配列Gの長さ: " + 配列G.長さ);
int[][][] arrayH = new int[][][]{{{1,2,3},{4,5,6},{7,8,9},{10,11,12} }};
System.out.println("配列Hの長さ: " + 配列H.長さ);
dummyArray[] arrayI = {new dummyArray(),new dummyArray()} //カスタム配列タイプ
System.out.println("配列Iの長さ: " + 配列I.長さ);
System.out.println("arrayI[1]: " + arrayI[1].getValue());
dummyArray[] arrayK = 新しい dummyArray[5];
System.out.println("arrayK[0]: " + arrayK[0]);
for(int i = 0; i < arrayK.length; i++){
arrayK[i] = 新しい dummyArray();
}
System.out.println("arrayK[0]: " + arrayK[0].getValue());
}
}
クラスダミー配列{
プライベート静的 int temp;
プライベートfinal int arrayValue = temp++;
public int getValue(){
配列値を返します。
}
}
出力:
配列Bの長さ: 5
配列Aの長さ: 10
配列Cの長さ: 4
配列Eの長さ: 1
配列Gの長さ: 3
配列Hの長さ: 1
配列Iの長さ: 2
配列I[1]: 1
配列K[0]: null
配列K[0]: 2
int[][] arrayB = 新しい int[10][];
System.out.println("配列Bの長さ: " + 配列B.長さ);
int[][] arrayC = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7} ,};//後のカンマに注意してください
System.out.println("配列Cの長さ: " + 配列C.長さ);
int[][] arrayD = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7} 、{}};
System.out.println("配列Dの長さ: " + 配列D.長さ);
}
}
出力:
配列Aの長さ: 15
配列Bの長さ: 10
配列Cの長さ: 3
配列Dの長さ: 4
[譲渡と参照]
JAVA 配列が初期化されると、配列への参照のみが存在し、配列には記憶領域は割り当てられません。したがって、配列間のコピーは、同じオブジェクトを操作するため、単純に「=」代入を使用することはできません。次の手順:
}
}
出力:
私は testA です、何も変わっていません:testA
私は arrayA です、何も変更されていません:arrayB は変更されました
[配列コピー]
JAVAで配列をコピーする方法:
1. FOR ループを使用してすべての要素または指定された要素をコピーしますが、効率は低くなります。
2. clone メソッドを使用して、参照の代わりに配列の値を取得します。ただし、cloneでは指定した要素をコピーすることができず、柔軟性が低いです。
3. System.arraycopy(src, srcPos, dest, destPos, length) メソッドを使用します。Java 標準クラス ライブラリには、静的メソッド System.arraycopy() が用意されており、これを使用すると、for ループよりもはるかに高速になります。 .arraycopy() は、すべての型がオーバーロードされているためです。基本型配列とオブジェクト配列はどちらも System.arraycopy() を使用してコピーできますが、オブジェクト配列は参照のみをコピーし、オブジェクトのコピーが 2 つ存在することはありません。これを浅いコピーと呼びます。
src: ソース配列;
srcPos: コピーされるソース配列の開始位置。
dest: 宛先配列;
destPos: 宛先配列が配置される開始位置。
長さ: コピーの長さ。
注: System.arraycopy() は自動パッケージ化と自動アンパックを実行しないため、2 つの配列は同じ型であるか、同じ型の配列に変換できる必要があります。同時に、このメソッドを使用して配列自体をコピーすることもできます。
int[] テスト ={0,1,2,3,4,5,6};
System.arraycopy(テスト,0,テスト,3,3);
結果は次のようになります: {0,1,2,0,1,2,6};
テスト手順は次のとおりです。
//クローンメソッド
int[] arrayB = 新しい int[9];
arrayB = array.clone();
//テスト
配列B[1] = 19;
for(int i = 0; i < arrayB.length; i++){
System.out.print(arrayB[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
System.out.println("");
//System.arrayCopy メソッド
int[] arrayC = 新しい int[9];
System.arraycopy(array, 0, arrayC, 0, arrayC.length);
//テスト
配列C[1] = 19;
for(int i = 0; i < arrayC.length; i++){
System.out.print(arrayC[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
}
}
String[][] arrayD = {{"a","b"},{"c","d"}};
String[][] arrayE = {{"a","b"},{"c","d"}};
System.out.println(Arrays.deepEquals(arrayD, arrayE));
}
}
[配列を返す]
C および C++ は配列を返すことはできず、配列へのポインターのみを返します。配列を返すと配列のライフ サイクルの制御が難しくなり、メモリ リークが発生しやすくなるからです。 Java では配列を直接返すことができ、ガベージ コレクション メカニズムによって配列をリサイクルできます。
【配列とコンテナの変換】 【基本型配列が変換できない】
配列をリストに変換します。
int[] arrayB = {1,2,3};
リスト listB = java.util.Arrays.asList(arrayB);
System.out.println("listB: " + listB);
Integer[] arrayC = {1,2,3};
リスト listC = java.util.Arrays.asList(arrayC);
System.out.println("listC: " + listC);
}
}
出力:
リストA: [a、b、c]
リストB: [[I@de6ced]
リストC: [1、2、3]
リストを配列に変換
String[] strings = new String[list.size()];
配列 = list.toArray(文字列);
for(int i = 0, j = array.length; i < j; i++){
System.out.print(array[i] + ",");
}
}
}
出力は次のとおりです。
リスト: [テストA、テストB、テストC]
テストA、テストB、テストC
public static String[] arrayUnique(String[] array){
List<String> list = new ArrayList<String>();
for(int i = 0, j = array.length; i < j; i++){
if(!list.contains(array[i])){
list.add(配列[i]);
}
}
String[] strings = new String[list.size()];
String[] arrayUnique = list.toArray(strings);
arrayUnique を返します。
}
}
Double[] arrayB = 新しい Double[1000000];
for(int i = 0, j = arrayB.length; i < j; i++){
arrayB[i] = Math.ceil(Math.random()*1000);
}
System.out.println("開始");
長い startTime = System.currentTimeMillis();
arrayUnique(配列);
long endTime = System.currentTimeMillis();
System.out.println("配列固有の実行時間: " +(endTime - startTime) +"ms");
長い startTimeB = System.currentTimeMillis();
arrayUnique(arrayB);
long endTimeB = System.currentTimeMillis();
System.out.println("arrayB 固有の実行時間: " +(endTimeB - startTimeB) +"ms");
}
public static Double[] arrayUnique(Double[] array){
List<Double> list = new ArrayList<Double>();
for(int i = 0, j = array.length; i < j; i++){
if(!list.contains(array[i])){
list.add(配列[i]);
}
}
Double[] doubles = new Double[list.size()];
Double[] arrayUnique = list.toArray(doubles);
arrayUnique を返します。
}
}
出力:
始める
アレイ固有の実行時間: 577ms
arrayB 固有の実行時間: 5663ms