Javaの配列をコピーしたいとき、普通にコピーすると元の配列と同じところを見に行くことになる。同じ配列が二個できて、利用できるようになるわけではないということだ。
このページではJavaの配列のコピー方法をまとめてご紹介した。
Javaの配列をコピーする方法
配列の要素をデータ処理する場合、元のデータを残してデータを並べ替えたり、あるグループのデータだけを取り出したりする場合がある。
このような時、元のデータをそのまま取っておくなら、新たな配列を作ってコピーする必要がある。
配列をコピーする方法はいくつかある。
forループを使ってコピーのためのコードを最初から書いてもよいが、Javaのクラスライブラリを使えばもっとスマートに配列をコピーできる。
はじめに、forループを使って配列をコピーする方法をみてみよう。
forループを使った配列コピーのサンプルプログラム
このプログラムは、配列numbersを作った後に新たに配列newNumbersを作り、forループを使って元の配列の値を3個コピーしている。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class CopyOfArrayByLoop { public static void main(String[] args) { int[] numbers = {12,24,36};//[1] int[] newNumbers = new int[3];//[2] for (int index = 0; index < numbers.length; index++) {//[3] newNumbers[index] = numbers[index];//[4] } for (int index = 0; index < numbers.length; index++) {//[5] System.out.println("[6] newNumbers[" +index + "] = " + newNumbers[index]); } } } |
実行結果
1 2 3 |
[6] newNumbers[0] = 12 [6] newNumbers[1] = 24 [6] newNumbers[2] = 36 |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1] int型で3個の要素数を持つ配列参照変数numbersを宣言し、初期値を代入する
- [2] int型で3個の要素数を持つ配列参照変数newNumbersを作る。
- [3]-[4] forループによりnewNumbersの先頭からnumbersの3つの値を代入する。
- [5] 配列の全ての値をひとつずつ表示する。
では、次に配列をコピーするために使えるJavaのクラスライブラリの使い方を紹介しよう。
Java 標準クラスライブラリを使用する
Java標準のライブラリの中にあるパッケージjava.langにSystemクラスがある。そのSystemクラスに配列をコピーするarraycopyクラスメソッドがある。このメソッドを使うとふたつの配列の間で要素をコピーすることができる。
コピー先の配列を準備して、そこにコピー元の配列をコピーする。このような方法ために、このクラスメソッドが使える。コピー元とコピー先の配列のコピー開始位置やコピーする要素の数を指定することができる。
1 2 3 4 5 |
System.arraycopy ( コピー元配列変数名, コピー元の開始位置, コピー先配列変数名, コピー先の開始位置, コピーする要素の数 ) |
書き方の基本はこれだ。
このクラスライブラリは、途中で何かの不具合が見つかると例外が発生して、コピーが中断する。このとき,既にコピーされた要素はそのままなので注意が必要である。
System.arraycopyを使ったサンプルプログラム
それでは実際にサンプルプログラムを確認してみよう。
このサンプルプログラムは、最初にコピー先の配列を準備しておいて、そこにコピー元の配列の要素をコピーする。
ここでは,配列の要素がプリミティブ型の場合と参照型の場合のサンプルプログラムを用意した。
配列要素がプリミティブ型
1 2 3 4 5 6 7 8 9 10 |
import java.util.Arrays; public class CopyOfArrayByLibrary { public static void main(String[] args) { int[] array = {12,24,36};//[1] int[] newArray = new int[3];//[2] System.arraycopy(array,0,newArray,0,array.length);//[3] System.out.println("[4] " + Arrays.toString(newArray)); } } |
実行結果
1 |
[4] [12, 24, 36] |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1] int型の配列参照変数arrayを宣言し、3個の初期値を代入する。
- [2] int型で3個の要素数を持つ配列参照変数newArrayを作る。
- [3] arraycopyクラスメソッドを使って、配列arrayの要素を配列newArrayにコピーする。
- [4]配列newArrayの値を表示する。
配列要素が参照型
1 2 3 4 5 6 7 8 9 10 |
import java.util.Arrays; public class CopyOfReferenceTypeArrayByLibrary { public static void main(String[] args) { String[] array = {"ab","cd","ef"};//[1] String[] newArray = new String[3];//[2] System.arraycopy(array,0,newArray,0,array.length);//[3] System.out.println("[4] " + Arrays.toString(newArray)); } } |
実行結果
1 |
[4] [ab, cd, ef] |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1] 文字列型の配列arrayを宣言し、3個の初期値を代入する。
- [2] 文字列型で3個の要素数を持つ配列参照変数newArrayを作る。
- [3] arraycopyクラスメソッドを使って、配列arrayの要素を配列newArrayにコピーする。
- [4] 配列newArrayの要素を表示する。
配列の浅い(Shallow)と深い(Deep)コピー
配列のコピーには、Shallow コピーとDeepコピーがある。
Shallowコピーは、配列の入れ物はひとつで、新たに宣言した配列参照変数に配列の場所を指す配列参照変数の値だけをコピー、つまり代入する。このコピーでは、入れ物はひとつなので配列の要素の値を変更すると、コピー元もコピー先も両方とも値が変化する。
一方、Deepコピーは新たな配列参照変数を宣言し、配列の入れ物も新たに作って、配列の要素のほうをコピーする。
このコピーでは入れ物は別なので、配列の要素を変更しても他方の要素の値が変更されることはない。
では、実際のプログラムを見てみよう。
Shallowコピーのサンプルプログラム
このプログラムは、配列のShallowコピーを行う。コピー先の値を変更した時、コピー先の要素の値も変化することが確認できる。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.Arrays; public class ShallowCopy { public static void main(String[] args) { int[] array = {12,24,36};//[1] int[] newArray = array;//[2] System.out.println("[3] 元の配列 = " + Arrays.toString(array)); System.out.println("[4] Shallowコピー = " + Arrays.toString(newArray)); newArray[1] = 999;//[5] System.out.println("[6] 元の配列 = " + Arrays.toString(array)); System.out.println("[7] Shallowコピー = " + Arrays.toString(newArray)); } } |
実行結果
1 2 3 4 |
[3] 元の配列 = [12, 24, 36] [4] Shallowコピー = [12, 24, 36] [6] 元の配列 = [12, 999, 36] [7] Shallowコピー = [12, 999, 36] |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしていこう。
- [1] int型で3個の要素数を持つ配列参照変数arrayを宣言し、初期値を代入する
- [2] int型で配列参照変数newArrayを作り,参照変数arrayの値を初期値として代入する。
- [3]-[4] arrayとnewArray配列の全ての値をひとつずつ表示する。
- [5] 配列newArrayの2番目の要素に999を代入する。
- [6]-[7] arrayとnewArray配列の全ての値をひとつずつ表示する。
Deepコピーのサンプルプログラム
このプログラムは、配列のDeepコピーを行う。コピー先の値を変更した時、コピー先の要素の値は変更されないことが確認できる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.Arrays; public class DeepCopy { public static void main(String[] args) { int[] array = {12,24,36};//[1] int[] newArray = new int[3];//[2] System.arraycopy(array,0,newArray,0,array.length);//[3] System.out.println("[4] 元の配列 = " + Arrays.toString(array)); System.out.println("[5] Deepコピー = " + Arrays.toString(newArray)); newArray[1] = 999;//[6] System.out.println("[7] 元の配列 = " + Arrays.toString(array)); System.out.println("[8] Deepコピー = " + Arrays.toString(newArray)); } } |
実行結果
1 2 3 4 |
[4] 元の配列 = [12, 24, 36] [5] Deepコピー = [12, 24, 36] [7] 元の配列 = [12, 24, 36] [8] Deepコピー = [12, 999, 36] |
サンプルプログラムの説明
それでは簡単にプログラムの解説をしていこう。
- [1] int型で3個の要素数を持つ配列参照変数arrayを宣言し、初期値を代入する
- [2] int型で3個の要素数を持つ配列参照変数newArrayを作る。
- [3] arrayからnewArrayに配列の要素をすべてコピーする。
- [4]-[5] arrayとnewArray配列の全ての値をひとつずつ表示する。
- [6] 配列newArrayの2番目の要素に999を代入する。
- [7]-[8] arrayとnewArray配列の全ての値をひとつずつ表示する。
まとめ
このページではJavaの配列のコピー方法についてまとめてきた。はじめは混乱するかもしれないが、重要な考え方だ。
参考にしていただければと思う。
コメント