またあったね!:) 前回のレッスンでは、配列(Java 配列)などのデータ構造について学び、配列の作成方法、データの入力方法、および配列がメモリに格納される方法を学びました。今日は、実際の仕事で頻繁に遭遇するいくつかのタスクと配列の操作例を見ていきます。たとえば、次の状況を想像してください。ランダムな順序で書かれた 10 個の数値の配列があります。
//array Java, example
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
私たちのタスクは、この配列を最小値から最大値の昇順に並べ替えることです。最終的には次のようになります。
[-234, -2, 16, 26, 35, 43, 80, 92, 99, 167]
どうやってこれを行うのでしょうか?このタスクは簡単ではありません。これまでにこれを行ったことはありません :/ 何かアイデアはありますか? 推測してみてください。たとえば、次のことができます。
- 配列のすべての要素を反復処理します。各要素を次の要素と比較します (
[0]
with[1]
、[1]
with[2]
、[2]
with[3]
など)。現在の配列要素が次の要素より大きい場合、それらを交換して次の要素に進みます。そうでない場合は、そのままにして次に進みます。 - したがって、配列の要素を最初に通過した後、最大値 (167) が最後のセルにあることが保証されます。
- ここで、配列のすべての要素をもう一度調べて、index の要素から始めて
[0]
最後から 2 番目の要素 (最大の数値がすでにその位置にあります) まで調べて、同じ比較と交換を行ってみましょう。
最後に、最後から 2 番目のセルに 2 番目に高い値 (99) が表示されます。 - 配列内の要素がマイナス 1 になるまでこの作業を繰り返してみましょう。
public class Main {
public static void main(String[] args) {
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
for (int i = numbers.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
/* Compare the elements in pairs,
if they are in the wrong order,
then swap them */
if (numbers[j] > numbers[j + 1]) {
int tmp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = tmp;
}
}
}
}
}
うーん...少し複雑ですね -_- 一般的な動作原理は明らかであっても、このような一見単純なタスクを解決するには、かなりの量のコードを記述する必要があります。そうですね、私たちは自分自身を過大評価しているだけかもしれません? おそらく、私たちがこれまで引き受けてきた仕事は、私たちにとって難しすぎたのでしょう。もっと簡単なことをやってみましょう。たとえば、同じ数値の配列を考えてみましょう。
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
私たちのタスクは、その内容を別の配列にコピーすることです。
int [] numbersCopy = new int[10];
すでに持っている配列に関する知識を使用してこれを行う方法を考えてみてください。たとえば、配列をループしてnumbers
、その要素を 1 つずつ に書き込むことができますnumbersCopy
。
public class Main {
public static void main(String[] args) {
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
int [] numbersCopy = new int[10];
for (int i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}
}
}
まあ、多かれ少なかれそれはできました!問題は解決されたように見えますが、繰り返しになります。頻繁に実行する必要がある場合、コードには同一のループが多数含まれることになります。実際、これらの問題やその他の問題は、Java の作成者によって長い間解決されてきたため、「車輪の再発明」を行ったり、独自の解決策のためのコードを作成したりする必要はありません。
Java 配列クラス
特別な Java クラスは、配列を操作する際の典型的な問題の解決に役立ちますArrays
。Java プログラマーが作業中に遭遇する最も一般的な問題を解決するメソッドがこのクラスに追加されました。たとえば、配列をソートするタスクは、私たち自身が解決策を考え出そうと試みましたが、次の 1 行で解決できます。
public class Main {
public static void main(String[] args) {
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers));
}
}
このメソッドはArrays.sort()
配列をソートします。さらに、組み込まれたアルゴリズムにより、私たちが作成したコードよりもはるかに効率的になります。コンソール出力:
[-234, -2, 16, 26, 35, 43, 80, 92, 99, 167]
注意: 配列を文字列に変換するには、別のクラス メソッドArrays
-を使用しましたArrays.toString()
。Java 配列自体はをオーバーライドしませんtoString()
。それで、ただ書くと
System.out.println(numbers.toString());
toString()
クラス メソッドが呼び出されますObject
。配列の場合、出力は次のようになります。
[I@4554617c
ここでは、結論がこのようになる理由については詳しく説明しませんが、重要なことは、これは明らかに私たちが必要としているものではないということです。しかし、Arrays.toString() は私たちが望んでいた通りのことをしてくれました。ちなみに、コピーの問題もクラスで簡単に解決できますArrays
。
public class Main {
public static void main(String[] args) {
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
int [] numbersCopy = Arrays.copyOf(numbers, numbers.length);
System.out.println(Arrays.toString(numbersCopy));
}
}
このメソッドには、Arrays.copyOf()
元の配列 (そこから値をコピーする必要があります) と、データをコピーする新しい配列の長さを渡します。この場合、長さとして指定しましたnumbers.length
。配列全体をコピーしたいと考えています。最初のいくつかの要素のみをコピーしたい場合は、新しい配列に短い長さを指定できます。
public class Main {
public static void main(String[] args) {
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
int [] numbersCopy = Arrays.copyOf(numbers, 4);
System.out.println(Arrays.toString(numbersCopy));
}
}
ここでは、新しい配列の長さを 4 に指定しています。したがって、最初の 4 つの要素のみがnumbers
新しい配列にコピーされます。コンソール出力:
[167, -2, 16, 99]
ちなみに、配列の一部を最初からではなく「途中から」コピーする必要がある場合は、Arrays
次のようにすることもできます。
public class Main {
public static void main(String[] args) {
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
int [] numbersCopy = Arrays.copyOfRange(numbers, 2,6);
System.out.println(Arrays.toString(numbersCopy));
}
}
結論:
[16, 99, 26, 92]
セル 2 (両端を含む) からセル 6 (両端を含めない) まで の数値が新しい配列にコピーされました。さらに、2 つの配列を相互に比較する必要がある場合があります。メソッドと同様にtoString()
、配列自体はメソッドをオーバーライドしませんequals()
。したがって、次のように比較してみると、次のようになります。
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
int[] numbers2 = {1, 2, 3};
System.out.println(numbers.equals(numbers2));
}
}
結果が得られますfalse
。Object.equals()
結局のところ、リンクを比較するメソッドはと呼ばれることになります。そしてもちろんそれらは違います!ただし、リンクではなく配列の内容を比較する必要があります。このクラスには、必要なことを正確に実行する Arrays
オーバーライドされたメソッドが含まれています。equals()
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
int[] numbers2 = {1, 2, 3};
System.out.println(Arrays.equals(numbers, numbers2));
}
}
結論:
true
ちなみに、このクラスはArrays
通常の配列だけでなく、2 次元の配列でも正常に動作します。
public class Main {
public static void main(String[] args) {
int[][] numbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] numbersCopy = Arrays.copyOf(numbers, numbers.length);
System.out.println("Are these two-dimensional arrays equal to each other?");
System.out.println(Arrays.deepEquals(numbers, numbersCopy));
System.out.println(Arrays.deepToString(numbersCopy));
}
}
結論:
Равны ли эти двумерные массивы между собой?
true
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ご覧のとおり、このメソッドはArrays.copyOf()
2 次元配列のコピーに対応しています。この場合、2次元配列をコピーすると、いわゆる「浅いコピー」が発生することに注意してください。また、2 次元配列を比較してコンソールに出力するための特別なメソッドが提供されていますdeepEquals
。deepToString()
将来的には、Java の作成者が、プログラマが作業中に遭遇する多くの典型的な状況を予見し、Java に既成のソリューションを実装したことを何度も目にするでしょう (そしてそれを嬉しく思います)。これらのソリューションを使用することは、車輪を再発明するよりもはるかに簡単で便利ですよね? :) Oracle のArrays
Web サイトにあるクラスのドキュメントを必ずお読みください。勉強頑張ってください!
GO TO FULL VERSION