Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaで配列をコピーする4つの方法を徹底解説

Javaで配列を扱っていると、既存の配列のコピーを作成したくなる場面がよくあります。例えば、カフェを経営していて季節限定メニューを作りたい場合、元のメニューをベースに新しいメニュー用の配列コピーを作成したいと思うでしょう。

Javaには配列をコピーする方法がいくつかあります。この記事では、特によく使われる4つの方法を取り上げ、コードを行ごとに解説していきます。読み終える頃には、Javaでの配列コピーをマスターできているはずです。

Javaにおける配列の基本

Javaにおいて、配列とは同じ型の値を複数格納できるコンテナです。例えば、書籍のリストや、ダーツゲームでプレイヤーが獲得したスコアの一覧などを保存するのに使えます。

配列は、似たような値を多数扱いたい場合に便利です。すべての値を1つのコレクションにまとめられるため、コードを簡潔にでき、同じ処理を複数の値に対して一括で実行することもできます。

例えば、カフェで販売しているコーヒーのリストを格納する配列を作りたいとしましょう。次のようなコードで実現できます。

String[] coffees = {"Espresso", "Mocha", "Latte", "Cappuccino", "Pour Over", "Flat White"};

この例では、String型の値を格納する coffees という配列を宣言しています。配列には6つの値が含まれています。

配列内の各要素には、0から始まるインデックス番号が割り当てられます。このインデックス番号を使うことで、配列内の個々の要素を参照できます。

Java配列の基本がわかったところで、次は配列の内容をコピーするための方法を見ていきましょう。

方法1: 代入演算子を使って配列をコピーする

配列をコピーする最も一般的な方法のひとつが、代入演算子(=)を使う方法です。

代入演算子は値を変数に代入するために使われます。これを利用すると、既存の配列の内容を新しい変数に代入でき、結果として配列のコピーが作成されます。

再びカフェの例に戻りましょう。coffees 配列をコピーして、夏季コーヒーメニューのベースにしたいとします。次のようなコードで配列のコピーを作成できます。

class CopyAssignment {
	public static void main(String[] args) {
		String[] coffees = {"Espresso", "Mocha", "Latte", "Cappuccino", "Pour Over", "Flat White"};
		String[] summer_coffees = coffees;

		for (String c: summer_coffees) {
			System.out.print(c + ",");
		}
	}
}

このコードを実行すると、次の出力が得られます。

Espresso, Mocha, Latte, Cappuccino, Pour Over, Flat White,

コードを分解してみましょう。CopyAssignmentクラス内の最初の行では、標準のコーヒーメニューを格納する coffees という配列を宣言しています。

次の行では、代入演算子を使って coffees の値を summer_coffees という新しい配列に代入しています。その後、「拡張forループ」を作成し、summer_coffees 配列の各要素を順番に取り出してコンソールに出力します。

ただし、この方法には注意点があります。片方の配列の要素を変更すると、もう片方の配列も変更されてしまうのです。つまり、summer_coffees リスト内の「Latte」を「Summer Latte」に変更すると、coffees リストの方も変更されてしまいます。

方法2: forループを使って配列をコピーする

先ほどの代入演算子によるコピーは、いわゆる「シャローコピー(浅いコピー)」です。これは、既存の配列オブジェクトを新しい変数に代入しているためで、どちらか一方のオブジェクトを変更すると両方が変更されます。2つのオブジェクトはリンクされている状態なのです。

しかし、実際には「ディープコピー(深いコピー)」が必要になることが多いでしょう。ディープコピーでは、既存のオブジェクトから値を取り出し、まったく新しい配列オブジェクトを作成します。ディープコピーを作成すれば、元の配列に影響を与えることなく新しい配列を自由に変更できます。

ディープコピーを作成する方法のひとつが、for ループを使って配列の内容を反復処理しながら新しい配列を作る方法です。

例えば、coffees 配列のディープコピーとして summer_coffees を作りたいとしましょう。夏の間に提供する新しいコーヒーを反映させるために summer_coffees の内容を変更する予定なので、ディープコピーである必要があります。

for ループを使ってディープコピーを作成するコードは以下の通りです。

import java.util.Arrays;

class LoopCopy {
	public static void main(String[] args) {
		String[] coffees = {"Espresso", "Mocha", "Latte", "Cappuccino", "Pour Over", "Flat White"};
		String[] summer_coffees = new String[6];

		for (int i = 0; i < coffees.length; ++i) {
			summer_coffees[i] = coffees[i];
		}

		System.out.println(Arrays.toString(summer_coffees));
	}
}

このコードを実行すると、出力は次のようになります。

[Espresso, Mocha, Latte, Cappuccino, Pour Over, Flat White]

ご覧の通り、元の配列のコピーが作成されました。このコードの動作をステップごとに説明します。

  1. まず、toString() メソッドを含む java.util.Arrays をインポートします。このメソッドは、例の最後で配列をコンソールに出力するために使用します。
  2. 標準メニューのコーヒーリストを格納する coffees という配列を宣言します。
  3. 6つの値を格納する summer_coffees という配列を初期化します。
  4. forループを使って、coffees リストの各要素を反復処理します。
  5. forループが実行されるたびに、summer_coffees のインデックス i の位置に、coffees のインデックス i の要素が代入されます。
  6. 最後に Arrays.toString() を使って summer_coffees を文字列に変換し、コピーされた要素を含む新しい配列をコンソールに出力します。

方法3: copyOfRange()メソッドを使う

Javaの copyOfRange() メソッドは、配列をコピーするために使用されます。このメソッドは java.util.Arrays クラスの一部です。copyOfRange() メソッドの構文は次の通りです。

import java.util.arrays;

DataType[] newArray = Arrays.copyOfRange(oldArray, indexPos, length);

copyOfRange() メソッドの構文を分解してみましょう。

  1. DataType: 新しい配列が格納するデータの型です。
  2. newArray: 新しい配列の名前です。
  3. oldArray: 値を newArray にコピーしたい元の配列です。
  4. indexPos: oldArray 内でコピー操作を開始する位置です。
  5. length: oldArray から newArray へコピーする値の数です。

それでは、copyOfRange() メソッドの動作を確認する例を見てみましょう。先ほどの coffees 配列のコピーを作成したいとします。次のようなコードで実現できます。

import java.util.Arrays;

class CopyUsingRange {
	public static void main(String[] args) {
		String[] coffees = {"Espresso", "Mocha", "Latte", "Cappuccino", "Pour Over", "Flat White"};

		String[] summer_coffees = Arrays.copyOfRange(coffees, 0, coffees.length);
		System.out.println("Summer coffees: " + Arrays.toString(summer_coffees));
	}
}

このコードを実行すると、次の出力が得られます。

Summer coffees: [Espresso, Mocha, Latte, Cappuccino, Pour Over, Flat White]

コードを分解してみましょう。

  1. 例で使用する copyOfRange() メソッドと toString() メソッドを含む java.util.Arrays ライブラリをインポートします。
  2. 標準メニューのコーヒーを格納する coffees という配列を宣言します。
  3. summer_coffees という配列を宣言し、copyOfRange() メソッドを使って coffees 配列のコピーを作成します。指定するパラメータは以下の通りです。
    1. coffees: コピーしたい配列の名前です。
    2. 0: coffees 配列のインデックス0からコピーを開始することを指定します。
    3. coffees.length: リスト内のすべての値をコピーすることを指定します。
  4. 「Summer coffees: 」という文字列に続けて、結果の配列 summer_coffees をコンソールに出力します。

これで、coffees リストのコピーである summer_coffees が作成できました。

方法4: arraycopy()メソッドを使う

arraycopy() メソッドは、ある配列から別の配列へデータをコピーするために使用されます。このメソッドは System クラスの一部であり、既存の配列のコピーを柔軟にカスタマイズできるさまざまなオプションが用意されています。

arraycopy() メソッドの構文は次の通りです。

System.arraycopy(sourceArray, startingPos, newArray, newArrayStartingPos, length);

このメソッドを分解してみましょう。arraycopy() は5つのパラメータを受け取ります。

  • sourceArray: コピーしたい配列の名前です。
  • startingPos: sourceArray 内で値のコピーを開始するインデックス位置です。
  • newArray: 値のコピー先となる新しい配列の名前です。
  • newArrayStartingPos: コピーした値を挿入し始めるインデックス位置です。
  • length: newArray にコピーする要素の数です。

再びカフェの例に戻りましょう。coffees 配列のすべての値を summer_coffees という新しい配列にコピーしたいとします。次のようなコードで実現できます。

import java.util.Arrays;

class ArrayCopyMethod {
	public static void main(String[] args) {
		String[] coffees = {"Espresso", "Mocha", "Latte", "Cappuccino", "Pour Over", "Flat White"};
		String[] summer_coffees = new String[6];

		System.arraycopy(coffees, 0, summer_coffees, 0, coffees.length);
		System.out.println("Summer coffees: " + Arrays.toString(summer_coffees));
	}
}

このコードを実行すると、次の出力が得られます。

Summer coffees: [Espresso, Mocha, Latte, Cappuccino, Pour Over, Flat White]

コードの動作をステップごとに見ていきましょう。

  1. プログラムの冒頭で java.util.Arrays パッケージをインポートします。これには、プログラムの最後で作成した配列コピーを出力するために使用する toString() メソッドが含まれています。
  2. 標準メニューのコーヒーを格納する coffees という配列を宣言します。
  3. 6つの値を保持する summer_coffees という配列を初期化します。
  4. arraycopy() を使って coffees 配列のコピーを作成します。指定するパラメータは以下の通りです。
    1. coffees: コピー元の配列です。
    2. 0: coffees 配列内でコピーを開始する位置です。
    3. summer_coffees: コピーした値の追加先となる配列です。
    4. 0: summer_coffees 配列内でコピーした値の追加を開始する位置です。
    5. coffees.length: コピーする配列要素の数です。ここで coffees.length を指定することで、coffees リストの全要素をコピーできます。
  5. 「Summer coffees: 」というメッセージに続けて、作成した夏季コーヒーのリストを出力します。

まとめ

配列のコピーは、リストを扱う際によく行われる操作です。この記事では、Javaで配列をコピーする4つの方法を紹介しました。

まず、代入演算子を使ったシャローコピーの作成方法を解説し、次に for ループを使ったディープコピーの作成方法を説明しました。さらに、copyOfRange() メソッドを使った配列のコピー方法と、システムメソッドである arraycopy() を使った配列のコピー方法についても見てきました。

これであなたも、プロのようにJavaで配列をコピーできるようになったはずです!

  1. JavaScriptで配列を空にする4つの方法【サンプルコード付きで解説】

    JavaScriptで配列を空にする方法は、主に4つあります。それぞれ動作の仕組みや特徴が異なるため、目的に応じて適切な方法を選ぶことが大切です。配列を空にする4つの方法新しい空の配列を代入する:配列変数に、新しく作成した空の配列を代入します。最もシンプルな方法ですが、元の配列を参照している他の変数が残る点には注意が必要です。lengthプロパティを使う:配列のlengthプロパティに0を設定するだけで、すべての要素を削除できます。高速で、元の配列への参照も維持されるため、実務で最もよく使われる方法のひとつです。popメソッドを使う:配列の要素数が0になるまで、popメソッドで末尾の要素を繰り

  2. JavaのArrayIndexOutOfBoundsExceptionとは?発生原因と対処法を解説

    配列とインデックスの基本 配列(Array)とは、同じ型の要素を固定サイズで順番に格納するためのデータ構造(コンテナ/オブジェクト)です。配列のサイズ(長さ)は生成時に決定され、後から変更することはできません。 配列内の各要素の位置は「インデックス(添字)」と呼ばれます。Javaの配列は0始まりのため、最初の要素はインデックス0、2番目の要素はインデックス1、というように順に番号が割り当てられます。 配列の各要素へは、「配列名[インデックス]」という形式の式を使ってアクセスします。 System.out.println(myArray[3]); // 1457 が出力される たとえばサイズ7