ソート処理について

現場でたまにソートして出すという要件があります。
その時に毎回「どうやるんだっけ」となってしまうので、簡単に記事にしようと思います。

##配列の場合
これは簡単です。
Arraysクラスの**sort**メソッドを使用します。
昇順の場合は、

```java:Shojun.java
int[] numArray = {3,2,5};
// Arraysクラスのsortメソッドに並び替える配列を渡す。
Arrays.sort(numArray);
// ソートした配列を出力
Arrays.stream(numArray).forEach(System.out::println);
	
// 出力結果 2 3 5
```

降順の場合は、**sort**メソッドの第二引数にCollections.reverseOrder()を指定します。
ただし、<font color="Red">int型配列を並び替えるメソッドは用意されていない</font>為Integer型にすると良いでしょう。

```java:Kojun.java
Integer[] numArray = {3,2,5};
// Arraysクラスのsortメソッドに並び替える配列を渡す。
Arrays.sort(numArray,Collections.reverseOrder());
// ソートした配列を出力
Arrays.stream(numArray).forEach(System.out::println);
	
// 出力結果 5 3 2
```
上記と同じように、String型配列も**sort**メソッドを用いて並び替えができます。

##List
これも簡単です。
Collectionsクラスの**sort**メソッドを使用します。
昇順は、

```java:ShojunList.java
List<Integer> numList = Arrays.asList(3,2,5);
// Collectionsクラスのsortメソッドに並び替えるListを渡す。
Collections.sort(numList);
// ソートしたListを出力
numList.forEach(System.out::println);

// 出力結果 2 3 5
```

降順の場合は、**sort**メソッドの第二引数にCollections.reverseOrder()を指定します。

```java:KojunList.java
List<Integer> numList = Arrays.asList(3, 2, 5);
// Collectionsクラスのsortメソッドに並び替えるListを渡す。
Collections.sort(numList, Collections.reverseOrder());
// ソートしたListを出力
numList.forEach(System.out::println);

// 出力結果 5 3 2
```
String型が入ったListも同じようにソート出来ます！！

##Map
まずキーでソートしたい場合ですが、昇順はTreeMapに入れてしまいましょう。

```java:ShojunMap.java
Map<Integer, String> map = new TreeMap<Integer, String>();
// 値を設定。勝手に昇順になります！
map.put(2, "にさん");
map.put(3, "さんさん");
map.put(1, "いちさん");
// 出力
map.forEach((k, v) -> System.out.println(k + ":" + v));
		
// 出力結果 1:いちさん 2:にさん 3:さんさん
```
降順はTreeMapのコンストラクタにComparator.reverseOrder()を渡しましょう。

```java:kojunMap.java
Map<Integer, String> map = new TreeMap<Integer, String>(Comparator.reverseOrder());
// 値を設定。勝手に降順になります！
map.put(2, "にさん");
map.put(3, "さんさん");
map.put(1, "いちさん");
// 出力
map.forEach((k, v) -> System.out.println(k + ":" + v));
		
// 出力結果 3:さんさん 2:にさん 1:いちさん 
```
値でソートしたい場合は**comparingByValue**メソッドでマップの値を比較するコンパレータを取得し、sortedメソッドに渡してあげることで実現できます。
昇順の場合は、

```java:ShojunMap.java
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(2, "にさん");
map.put(3, "さんさん");
map.put(1, "いちさん");
// 値を昇順でソートし、linkedHashMapを作成
map = map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey,
		Map.Entry::getValue, (k1, k2) -> k1, LinkedHashMap::new));
// 出力
map.forEach((k, v) -> System.out.println(k + ":" + v));

// 出力結果 1:いちさん 3:さんさん 2:にさん 
```
HashMapだと投入順序が担保されませんので、LinkedHashMapに入れるのが良いです。

降順の場合は、**comparingByValue**メソッドの引数に**Comparator.reverseOrder()**を指定します。

```java:ShojunMap.java
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(2, "にさん");
map.put(3, "さんさん");
map.put(1, "いちさん");
// 値を降順でソートし、linkedHashMapを作成
map = map.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
				.collect(Collectors.toMap(Map.Entry::getKey,
						Map.Entry::getValue, (k1, k2) -> k1, LinkedHashMap::new));
// 出力
map.forEach((k, v) -> System.out.println(k + ":" + v));

// 出力結果 2:にさん 3:さんさん 1:いちさん 
```

##オブジェクト

下記のクラスがあるとします。


```java:Person.java
public class Person {

	private int age;
	private String name;

	public Person(int age, String name) {
		this.age = age;
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

```

当クラスを年齢順でソートしたい場合、**Comparatorインターフェースを実装し**、sortメソッドの引数に指定します。

```java:Person.java
// テスト用に、人情報を入れます。
List<Person> personList = new ArrayList<Person>();
personList.add(new Person(20, "Aさん"));
personList.add(new Person(16, "Cさん"));
personList.add(new Person(21, "Bさん"));
// 年齢順でソートします。
personList.sort((p1, p2) -> p1.getAge() - p2.getAge());

personList.forEach(p -> {
	System.out.println(p.getAge() + ":" + p.getName());
});

// 出力結果 16:Cさん 20:Aさん 21:Bさん

```

年齢が同じ場合は、名前でソートしたい時もあると思います。
その場合はまず年齢を比較して、同じだったら名前を比較すれば良いです。

```java:Person.java
// テスト用に、人情報を入れます。
List<Person> personList = new ArrayList<Person>();
personList.add(new Person(20, "Bさん"));
personList.add(new Person(16, "Cさん"));
personList.add(new Person(20, "Aさん"));
// 年齢順でソートします。年齢が同じ場合は名前順でソートします。
personList.sort((p1, p2) -> {
	int temp = p1.getAge() - p2.getAge();
	return temp == 0 ? p1.getName().compareTo(p2.getName()) : temp;
});

personList.forEach(p -> {
	System.out.println(p.getAge() + ":" + p.getName());
});
// 出力結果 16:Cさん 20:Aさん 20:Bさん

```

名前は文字列なので、compareToで比較します。

##終わりに
javaって一つの処理でも色々書き方があって難しいです。
今回取り上げたソート処理も、いくつか書き方がありもっと効率良く、わかりやすく記述する方法もあると思います。
参考程度で見ていただければ幸いです。