【Java入門】配列の操作について（1次元配列、2次元配列の宣言、インスタンス化、初期化および使用）

#目的

Java言語を含めたプログラミングの学習を始めたばかりの方、既学習者の方は復習用に、
今回は**配列**について学ぶために書いています。


[【Java入門目次】](https://qiita.com/morioheisei/items/6c7fc063c26e63d890ac)
・[変数と型](https://qiita.com/morioheisei/items/3d27e82d6cd88068dded)
・[型変換](https://qiita.com/morioheisei/items/28ab5fd69570e01cd317) 
・[変数のスコープ](https://qiita.com/morioheisei/items/c56ab32b68ce92d32206)
・[文字列の操作](https://qiita.com/morioheisei/items/e58adadd8535971b69be)
・配列の操作 ←今ここ
・[演算子](https://qiita.com/morioheisei/items/63088c61e8234dc1f7f5)
・[条件分岐](https://qiita.com/morioheisei/items/194cdc73a29bddade0a4)
・[繰り返し処理](https://qiita.com/morioheisei/items/e686e33b60c6a60e87f0)
・クラスについて（準備中）
・抽象クラス（準備中）
・インターフェース（準備中）
・カプセル化（準備中）
・モジュールについて（準備中）
・[例外処理について](https://qiita.com/morioheisei/items/d25d2b67e7530c1aab9d)
・[ラムダ式について](https://qiita.com/morioheisei/items/2bfcc3d8d8440b00e6a9)
・[Stream APIについて](https://qiita.com/morioheisei/items/3a7be38b4d3ef712ccb2)

#配列とは

変数は、一つの変数に対して一つの値データを入れる入れ物ですが（[変数についてはこちら](https://qiita.com/morioheisei/items/3d27e82d6cd88068dded)）、

配列を使用することで、`同じデータ型の複数のデータを一つの配列で管理することができる。`

500個分の値がある時、変数の場合では500個分用意しなければいけませんが、
配列の場合では、一つ配列を用意してその中に500個分のデータを格納できるということです。

また、その配列の中のデータを並び替えをしたり、一番大きな値を取得したりなども容易に出来てしまいます。


#1次元配列の宣言

配列を作成する時は、変数と同様にまずどのような値を扱うかのデータ型を決め、名前をつけて宣言する必要があります。

`データ型[] 配列名`と宣言します。


```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers; // int型の値を扱える配列の宣言

    // [] は、配列名の後ろでも構わない。
    String names[]; // String型の値を扱える配列の宣言
  }
}
```

#1次元配列のインスタンス化

宣言した配列にいくら値を詰めるのか、領域の確保をしてあげなければいけません。
`new [要素数]`での確保する領域の大きさ決めます。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers; // int型の値を扱える配列の宣言
    String names[]; // String型の値を扱える配列の宣言

    numbers = new int[50]; // numbers配列に50個分の値を格納するための領域を確保
    names = new String[3]; // name配列に3個分の値を格納するための領域を確保
  }
}
```

**配列の宣言と領域の確保を同時に行う事も可能です。**

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers = new int[50];// int型の値を扱える配列の宣言と50個分の領域を確保
    String names[] = new String[3]; // String型の値を扱える配列の宣言と3個分の領域を確保
  }
}
```
**要素数を指定しなければ、コンパイルエラーになるので注意しましょう。**

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers = new int[];// 要素数を指定していないため、コンパイルエラー
    String names[] = new String[]; // 要素数を指定していないため、コンパイルエラー
  }
}
```


配列の要素数は後から変更することは出来ず、
最初に配列の要素数を5で指定した場合は、その後の要素数はずっと5で固定されるので覚えておきましょう。

また、要素数は整数ではないとはないといけない点も覚えおきましょう。

#1次元配列の添え字（インデックス）と値の格納

配列の宣言、インスタンス化で値を格納する準備が整いました。
配列への値を代入は、`添え字（インデックス）`を使用します。
添え字（インデックス）は、配列の各々の要素につけられた通し番号で、0から始まります。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers = new int[5]; // int型の5つの要素が格納出来るnumbers配列を定義
    numbers[0] = 100; // 1番目には、100
    numbers[1] = 200; // 2番目には、200
    numbers[2] = 300; // 3番目には、300
    numbers[3] = 400; // 4番目には、400
    numbers[4] = 500; // 5番目には、500
  }
}
```

配列の各要素にアクセスする際も添え字（インデックス）を用います。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers = new int[5]; // int型の5つの要素が格納出来るnumbers配列を定義
    numbers[0] = 100; // 1番目には、100
    numbers[1] = 200; // 2番目には、200
    numbers[2] = 300; // 3番目には、300
    numbers[3] = 400; // 4番目には、400
    numbers[4] = 500; // 5番目には、500

    System.out.println(numbers[0]); // 100 が出力される
    System.out.println(numbers[3]); // 400 が出力される
  }
}
```
#1次元配列の初期化

上記までは配列の宣言、領域の確保、値（初期値）の代入を順を追って行っていましたが、

`配列の宣言、領域の確保、値（初期値）の代入を全て同時に行うことが出来ます。（配列の初期化）`

値を`{}`で囲み、カンマ区切りで各要素を記述していきます。
`データ型 [] 配列名 = {初期値1, 初期値2, 初期値3, 初期値4, 初期値5};`

また、作成した`要素の数を調べるにはlength`を使用します。
`配列名.length;` で要素数を取得する事が出来ます。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] numbers = {100, 200, 300, 400, 500}; // 配列の初期化
    int size = numbers.length; // numbers配列の要素数を取得 この場合、5が格納される

    System.out.println(numbers[0]); // 100 と出力される
    System.out.println(numbers[1]); // 200 と出力される
    System.out.println(numbers[2]); // 300 と出力される
    System.out.println(numbers[3]); // 400 と出力される
    System.out.println(numbers[4]); // 500 と出力される
    System.out.println(size); // 5 と出力される
    
    // この記述方法での配列の初期化も有効
    int[] id = new int[]{1, 2, 3};

    System.out.println(id[0]); // 1 と出力される
    System.out.println(id[1]); // 2 と出力される
    System.out.println(id[2]); // 3 と出力される
    System.out.println(id.length); // 3 と出力される
  }
}
```

#配列の要素外にアクセスした時

配列の要素のアクセスするには添え字（インデックス）を用いてアクセスしていましたが、
配列の要素外にアクセスをしようとしている時、コンパイルエラーにはなりませんが、実行時エラー（例外）が発生します。
詳しくは、[例外処理の記事](https://qiita.com/morioheisei/items/d25d2b67e7530c1aab9d)をご覧ください。

こちらでも軽く見てみましょう。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[] id = {1, 2, 3, 4, 5}; // 配列の要素数は5個

    // for文で6回のループを回す = id配列の要素を超える
    for(int i = 0; i < 6; i++) {
      // 一つずつ出力している
      System.out.println(id[i]);
    }
    System.out.println("id配列の中身を全て出力し終えました。");

  }
}
```

出力結果は、

```terminal:Terminal
1
2
3
4
5
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
        at Main.main(Main.java:195)
```
上記の様に出力されました。
ArrayIndexOutOfBoundsException例外が発生しています。
そして、id配列の中身を全て出力し終えました。と表示されていません。
この様に配列へアクセスしようとした時、要素外にアクセスしている場合、
例外が発生し、途中で処理が止まってしまうので気をつけましょう。


#2次元配列の宣言

添え字（インデックス）を2個で管理する2次元配列、それ以上の多次元配列もあります。
今回は2次元配列を説明していきます。

2次元配列では、[]を2つ使って、
`データ型[][] 配列名`と宣言します。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[][] numbers; // int型の値を扱える2次元配列の宣言

    // [][] は、配列名の後ろでも構わない。
    String strs[][]; // String型の値を扱える2次元配列の宣言
  }
}
```

#2次元配列のインスタンス化

1次元配列の時と同様に、宣言した配列にいくら値を詰めるのか、領域の確保をしてあげなければいけません。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[][] numbers; // int型の値を扱える2次元配列の宣言
    String strs[][]; // String型の値を扱える2次元配列の宣言

    // 3つの要素をもつ配列で、numbers[0]からnumbers[2]の各要素に、4つの要素をもてる領域を確保
    numbers = new int[3][4];

    // 2つの要素をもつ配列で、strs[0]からstrs[1]の各要素に、2つの要素をもてる領域を確保
    strs = new String[2][2];
  }
}
```
1次元配列と同様に、
**配列の宣言と領域の確保を同時に行う事も可能。**


```java:Main.java
class Main {
  public static void main(String[] args) {
    // int型の値を扱える2次元配列の宣言と領域を確保
    int[][] numbers = new int[3][4];

    // String型の値を扱える2次元配列の宣言と領域を確保
    String strs[][] = new String[2][2];
  }
}
```

また、`1次元目の配列の領域確保のみを行うことも可能。`
その場合、後から2次元目の要素数を決めることが出来ます。

```java:Main.java
class Main {
  public static void main(String[] args) {
    int[][] array; // int型の値を扱える2次元配列の宣言
    array = new int[3][]; // 3つの要素をもつ配列の領域を確保

    array[0] = new int[5]; // arrayの1番目の配列は5つの要素を格納できる
    array[1] = new int[3]; // arrayの2番目の配列は3つの要素を格納できる
    array[2] = new int[4]; // arrayの3番目の配列は4つの要素を格納できる

    // 配列の宣言と領域の確保を同時に行った時も同様
    String[][] strs = new String[2][]; // String型の配列の宣言、領域確保
    strs[0] = new String[6]; // strsの1番目の配列は6つの要素を格納できる
    strs[1] = new String[3]; // strsの2番目の配列は3つの要素を格納できる
  }
}
```

2次元配列の場合も要素数を後から変更することはできず、要素数は整数ではないといけません。


#2次元配列の添え字（インデックス）と値の格納

1次元配列と同様に添え字（インデックス）を用いて値の格納をします。


```java:Main.java
class Main {
  public static void main(String[] args) {
    int[][] numbers = new int[2][2]; // int型の値を扱える2次元配列の宣言
    numbers[0][0] = 100;
    numbers[0][1] = 200;
    numbers[1][0] = 300;
    numbers[1][1] = 400;

    System.out.println(numbers[0][0]); // 100 と出力される
    System.out.println(numbers[0][1]); // 200 と出力される
    System.out.println(numbers[1][0]); // 300 と出力される
    System.out.println(numbers[1][1]); // 400 と出力される
  }
}
```

#2次元配列の初期化

2次元配列でも、
`配列の宣言、領域の確保、値（初期値）の代入を全て同時に行うことが出来ます。（配列の初期化）`

同様に値を`{}`で囲み、カンマ区切りで各要素を記述していきます。
`データ型 [][] 配列名 = {
{初期値1, 初期値2, 初期値3, 初期値4, 初期値5},
{初期値6, 初期値7, 初期値8, 初期値9, 初期値10}
};`

また、作成した`要素の数を調べるにはlength`を使用します。
`配列名.length;` で要素数を取得する事が出来る。
さらにその配列の中の配列の長さを取得するには、
`配列名[添え字（インデックス）].length`で要素数を取得できます。

```java:Main.java
class Main {
  public static void main(String[] args) {
    // 1次元配列と同様に、配列の宣言、領域の確保、値の代入を一度に行うも可能。
    int[][] numbers = {
      {1, 2, 3, 4, 5},
      {6, 7, 8, 9, 10},
      {11, 12, 13},
      {16, 17}
    };
    System.out.println("numbers[0][4]の値 : " + numbers[0][4]); // numbers[0][4]の値 : 5 と出力される
    System.out.println("numbers[3][0]の値 : " + numbers[3][0]); // numbers[3][0]の値 : 16 と出力される

    System.out.println("numbersの長さ : " + numbers.length); // numbersの長さ : 4 と出力される
    System.out.println("numbers[0]の長さ : " + numbers[0].length); // numbers[0]の長さ : 5 と出力される
    System.out.println("numbers[2]の長さ : " + numbers[2].length); // numbers[2]の長さ : 3 と出力される
    System.out.println("numbers[3]の長さ : " + numbers[3].length); // numbers[3]の長さ : 2 と出力される
  }
}
```

#配列の使用方法の実例

ここからは1次元配列と2次元配列の簡単な使用方法を紹介します。

##小さい順に並び替え
java.util.Arraysクラスを使用するので、最初にimportする事を忘れないでください。
[OracleのArraysクラスについてはこちら](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Arrays.html)


```java:Main.java
import java.util.Arrays;

class Main {
  public static void main(String[] args) {
    // numbers配列を初期化（中の整数の順番はランダム）
    int[] numbers = {10, 1, 5, 6, 9};

    // Arraysクラスのsortメソッドを用いて小さい順に並び替えをする
    Arrays.sort(numbers);

    // numbers配列を一つずつ出力
    for(int number : numbers) {
      System.out.print(number + " "); // 1 5 6 9 10 と出力される
    }
  }
}
```

ランダムな整数が格納されていたnumbersは、sortメソッドを用いることで小さい順に並び替えできています。

次は文字列を並び替えてみます。

```java:Main.java
import java.util.Arrays;

class Main {
  public static void main(String[] args) {
    // names配列を初期化（中の名前の順番はランダム）
    String[] names = {"tanaka", "abe", "suzuki", "maeda"};

    // Arraysクラスのsortメソッドを用いてアルファベット順に並び替えをする
    Arrays.sort(names);

    // names配列を一つずつ出力
    for(String name : names) {
      System.out.print(name + " "); // abe maeda suzuki tanaka と出力される
    }
  }
}
```

ランダムな文字列が格納されていたnamesは、sortメソッドを用いることでアルファベット順に並び替えできています。

##最大値、最小値を取得する

```java:Main.java
class Main {
  public static void main(String[] args) {
    // 2次元配列numbersを初期化（中の整数の順番はランダム）
    int[][] numbers = {
      {2, 5, 6, -10, 100, 3},
      {-1000, 1, 20},
      {999, 12, 300, 50}
    };


    // 最大値を入れるmax変数を定義
    int max = 0;
    // 最小値を入れるmin変数を定義
    int min = 0;


    // numbers配列の1次元目を一つずつ見ていく
    for(int i = 0; i < numbers.length; i++) {

      // numbers[0]、numbers[1]、numbers[2]、の中身を一つずつ見ていく
      for(int j = 0; j < numbers[i].length; j++) {

        // numbers[0]、numbers[1]、numbers[2]の中で、maxより大きい数字があれば
        if(max < numbers[i][j]) {

          // その数値をmax変数に代入
          max = numbers[i][j];

        }

        // numbers[0]、numbers[1]、numbers[2]の中で、minより小さい数字があれば
        if(min > numbers[i][j]) {

          // その数値をmin変数に代入
          min = numbers[i][j];

        }

      }
    }

    System.out.println("numbers配列の最大値 : " + max); // numbers配列の最大値 : 999 と出力される
    System.out.println("numbers配列の最小値 : " + min); // numbers配列の最小値 : -1000 と出力される

  }
}
```

for文（繰り返し処理に関しては別記事を記載します）を用いて配列の要素を一つずつ比較しています。

大きい数字、小さい数字があれば、その都度最大値max変数、最小値min変数に値を代入しています。

#終わりに

簡単にではありますが、配列について学びました。

配列は要素数は固定でしたが、可変であるListというものもあります。
そちらは別記事で取り上げたいと思います。

複数のデータを用いることができるため、使用する機会は多いです。しっかりおさえておきたいですね。