回答:
あなたはSystem.arraycopy()を使って試すことができます
int[] src = new int[]{1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy( src, 0, dest, 0, src.length );
しかし、おそらくほとんどの場合clone()を使用する方が良いでしょう。
int[] src = ...
int[] dest = src.clone();
System.arraycopy
見ると、メソッドが開始する前にさまざまなことを確認する必要があることがわかります。これらのチェックの一部は、静的配列タイプに応じて、コピーループでは不要です。
clone()
は、250 000要素の中で最速であることが判明しました。
src.clone()
、新しい配列を割り当てて実行するよりも読みやすく、エラーの可能性がはるかに少ないことですarraycopy
。(また、たまたま高速です。)
あなたは使うことができます
int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();
同様に。
次のコピーを作成する場合:
int[] a = {1,2,3,4,5};
これは行く方法です:
int[] b = Arrays.copyOf(a, a.length);
Arrays.copyOf
a.clone()
小さなアレイよりも高速かもしれません。どちらの要素も同等に高速ですが、clone()は戻りますObject
ので、コンパイラーはへの暗黙のキャストを挿入する必要がありint[]
ます。次のようなバイトコードで確認できます。
ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
http://www.journaldev.com/753/how-to-copy-arrays-in-javaからの素晴らしい説明
Java配列のコピーメソッド
Object.clone():Objectクラスはclone()メソッドを提供します配列もオブジェクトであるため、このメソッドを使用して配列全体をコピーできます。この方法は、配列の部分的なコピーが必要な場合には適していません。
System.arraycopy():システムクラスarraycopy()は、配列の部分的なコピーを行うための最良の方法です。コピーする要素の総数と、コピー元とコピー先の配列のインデックス位置を簡単に指定できます。たとえば、System.arraycopy(source、3、destination、2、5)は、ソースの3番目のインデックスから宛先の2番目のインデックスまで、ソースから宛先に5つの要素をコピーします。
Arrays.copyOf():配列の最初のいくつかの要素または配列の完全なコピーをコピーする場合は、このメソッドを使用できます。明らかにSystem.arraycopy()のように用途が広いわけではありませんが、紛らわしくなく、使いやすいです。
Arrays.copyOfRange():開始インデックスが0でない場合に、配列のいくつかの要素をコピーする場合は、このメソッドを使用して部分配列をコピーできます。
これらの「配列をコピーするためのより良い方法」のすべてが本当にあなたの問題を解決するつもりはないと感じています。
あなたは言う
[...]のようなforループを試してみましたが、正しく機能していないようです。
そのループを見ると、機能しないことの明らかな理由はありません...
a
、b
配列と配列がめちゃくちゃになっている(たとえば、同じ配列a
をb
参照している)、またはa
配列の読み取りと更新を同時に行っている。どちらの場合も、コピーを実行する別の方法では根本的な問題を解決できません。
最初のシナリオの修正は明らかです。2番目のシナリオでは、スレッドを同期するいくつかの方法を理解する必要があります。アトミック配列クラスにはアトミックコピーコンストラクターやクローンメソッドがないため、役に立ちませんが、プリミティブミューテックスを使用して同期するとうまくいきます。
(あなたの質問には、これが確かにスレッドに関連していると私に思わせるヒントがあります。例えば、あなたのステートメントa
は常に変化しています。)
あなたはJavaでArrays.copyOf()を使用して試すことができます
int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
配列から長さを呼び出すすべてのソリューションで、コードに冗長なnullチェッカーを追加して例を検討してください:
int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
//What if array a comes as local parameter? You need to use null check:
public void someMethod(int[] a) {
if (a!=null) {
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
}
}
ホイールを発明せず、必要なすべてのチェックがすでに実行されているユーティリティクラスを使用することをお勧めします。Apache CommonsのArrayUtilsを検討してください。コードが短くなります:
public void someMethod(int[] a) {
int[] b = ArrayUtils.clone(a);
}
そこにある Apache commons
も使用できますArrays.copyOfRange
。
例:
public static void main(String[] args) {
int[] a = {1,2,3};
int[] b = Arrays.copyOfRange(a, 0, a.length);
a[0] = 5;
System.out.println(Arrays.toString(a)); // [5,2,3]
System.out.println(Arrays.toString(b)); // [1,2,3]
}
このメソッドはに似ていますがArrays.copyOf
、より柔軟です。どちらも内部で使用しますSystem.arraycopy
。
を参照してください。
配列のnullセーフコピーの場合Object.clone()
、この回答で提供されているメソッドでオプションを使用することもできます。
int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
Optional
オブジェクトは既存の配列への参照を持つ空のオブジェクトです。パフォーマンスへの影響については、このタイプの構成はJVM内のインライン化に適しているため、他のメソッドよりも影響が少ないため、実際に影響があるとは言えません。それをより複雑であると考えるかどうかは、スタイルの問題(関数型プログラミングと手続き型プログラミングだけではなく)の問題です。
あなたがいない生の配列と協力し、必要がある場合はArrayList
、次にArrays
何が必要があります。ソースコードを見ると、これらは配列のコピーを取得するのに最適な方法です。System.arraycopy()
非論理的なパラメーターを与えると、メソッドがチェックされない例外をたくさんスローするので、防御的なプログラミングには十分です。
Arrays.copyOf()
最初のNth
要素から新しい短い配列にコピーするいずれかを使用できます。
public static <T> T[] copyOf(T[] original, int newLength)
指定された配列をコピーし、(必要に応じて)ヌルで切り捨てまたはパディングして、コピーが指定された長さになるようにします。元の配列とコピーの両方で有効なすべてのインデックスについて、2つの配列には同じ値が含まれます。コピーでは有効であるが元のインデックスでは有効でないインデックスの場合、コピーにはnullが含まれます。そのようなインデックスは、指定された長さが元の配列の長さより大きい場合にのみ存在します。結果の配列は、元の配列とまったく同じクラスです。
2770
2771 public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772 T[] copy = ((Object)newType == (Object)Object[].class)
2773 ? (T[]) new Object[newLength]
2774 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775 System.arraycopy(original, 0, copy, 0,
2776 Math.min(original.length, newLength));
2777 return copy;
2778 }
またはArrays.copyOfRange()
、トリックも行います:
public static <T> T[] copyOfRange(T[] original, int from, int to)
指定された配列の指定された範囲を新しい配列にコピーします。範囲(from)の初期インデックスは、0とoriginal.lengthの間にある必要があります。original [from]の値は、コピーの最初の要素に配置されます(from == original.lengthまたはfrom == toを除く)。元の配列の後続の要素の値は、コピーの後続の要素に配置されます。範囲(to)の最終インデックスは、from以上である必要がありますが、original.lengthよりも大きい場合があります。この場合、nullは、インデックスがoriginal以上のコピーのすべての要素に配置されます。長さ-から。返される配列の長さは-からです。結果の配列は、元の配列とまったく同じクラスです。
3035 public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036 int newLength = to - from;
3037 if (newLength < 0)
3038 throw new IllegalArgumentException(from + " > " + to);
3039 T[] copy = ((Object)newType == (Object)Object[].class)
3040 ? (T[]) new Object[newLength]
3041 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042 System.arraycopy(original, from, copy, 0,
3043 Math.min(original.length - from, newLength));
3044 return copy;
3045 }
ご覧のとおり、これらはどちらも、System.arraycopy
実行しようとしていることが有効であることを示す防御ロジックを備えたラッパー関数です。
System.arraycopy
配列をコピーする最も速い方法です。