John Squirrels
レベル 41
San Francisco

配列クラス

ランダム グループに公開済み
人のメンバー
またあったね!:) 今日のレッスンでは、Java の Arrays クラスについて話します。前回のレッスンでは、配列と呼ばれるデータ構造について学びました。それらを作成し、データを入力する方法を学びました。そして、それらがメモリにどのように保存されるかを調べました。今日は、実際の作業でよく目にする配列を操作するいくつかのタスクと例を見ていきます。たとえば、次の状況を想像してください。10 個の乱数の配列があります。
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
私たちのタスクは、この配列を最小から最大の昇順に並べ替えることです。最終的には次のようになります: [-234, -2, 16, 26, 35, 43, 92, 99, 167] どうすればよいでしょうか? このタスクは簡単ではありません。これまで一度もやったことがありません :/ 何かアイデアはありますか? 推測してみてください。解決策の 1 つは次のとおりです。
  • 配列のすべての要素を調べます。各要素を次の要素と比較します ([0] と [1]、[1] と [2]、[2] と [3] など)。現在の要素が次の要素より大きい場合は、それらを交換してから、次の要素に進みます。そうでない場合は、そのままにして次に進みます
  • したがって、要素を最初に通過した後、最大値 (167) が最後のセルにあることが保証されます。
  • ここで、すべての要素をもう一度調べますが、今回は最後から 2 番目の要素へのインデックス [0] から開始し (最大の数値はすでにその位置にあります)、同じ比較と交換を行います。このパスの後、最後から 2 番目のセルに 2 番目に大きい値 (99) が表示されます。
  • このプロセスを配列要素の数だけ繰り返します。
アイデアはできました。あとはコードを書くだけです。次のようになります。 Arrays クラスとその使用法 - 2
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 not in the right 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];
配列についてすでに知っていることを使ってそれをどのように行うかを考えてみてください。たとえば、ループ内で数値配列を処理し、その要素をNumberCopyに順番に書き込むことができます。
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 の作成者によって長い間解決されてきました。「車輪の再発明」をして独自のソリューションをコーディングする必要はありません。配列を操作するときに一般的なタスクの実行に役立つ特別な静的クラス ( 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());
Object クラスのtoString()が呼び出されます。配列の場合、出力は次のようになります。 [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 要素のみが新しい配列にコピーされます。コンソール出力: [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 番目の配列の 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?");
       System.out.println(Arrays.deepEquals(numbers, numbersCopy));

       System.out.println(Arrays.deepToString(numbersCopy));
   }
}
出力: これらの 2 次元配列は等しいか? true [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ご覧のとおり、Arrays.copyOf()メソッドは 2 次元配列をコピーできました。また、このクラスには、2 次元配列を比較および表示するための特別なメソッドdeepEqualsおよびdeepToString()があります。将来、あなたは、Java の作成者がプログラマが頻繁に直面する多くの状況を予測し、そのための既製のソリューションを Java 言語に実装したことを繰り返し目にするでしょう (そしてその事実を喜ぶでしょう)。これらのソリューションを使用することは、車輪を再発明するよりもはるかに簡単で便利ですよね? :) Oracle のWeb サイトにある Arrays クラスのドキュメントを必ずお読みください。勉強頑張ってください!
コメント
  • 人気
  • 新規
  • 古い
コメントを残すには、サインインしている必要があります
このページにはまだコメントがありません