List在Java中做sort : Collection.sort()
===
## Discription
將資料收集進List後,常常會使用到sort,而此動作不需要自己去實作,在java.util.Collections提供sort的方法,Ex:
``Ex 1:``
```java=
import java.util.*;
public class Main
{
public static void main(String[] args) {
List<Integer> count = new ArrayList<>();
count.add(500);
count.add(50);
count.add(5000);
count.add(5);
Collections.sort(count);
for(int k: count)
System.out.println(k);
//Output:
//5
//50
//500
//5000
}
}
```
會是以升序排序
---
但如果List中存放的是自定義物件呢?
``Ex2``
```java=
import java.util.*;
public class Main
{
public static void main(String[] args) {
List P = Arrays.asList(
new Person("Justin", 1000,false),
new Person("Monica", 500,true),
new Person("Irene", 200,false)
);
Collections.sort(P);
}
}
class Person
{
private String name ;
private int money;
private boolean marry;
public Person(String name ,int money,boolean marry)
{
this.name = name;
this.money = money;
this.marry = marry;
}
}
```
執行結果會跳出:==ClassCastException==
Why??
因為==Collection並不知道要sort自定義物件的哪一個property==(i.e **name?** or **monry?** or **marry?**),也沒加以說明
---
## Comparable
Collections的sort()方法要求被排序的物件,必須實作java.lang.Comparable介面,這個介面有個compareTo()方法必須傳回大於0、等於0或小於0的數,
Collections的sort()方法在取得a物件跟b物件進行比較時,會先a物件扮演(Cast)為Comparable(也因此若物件沒實作Comparable,將會拋出ClassCastException,若使用了泛型宣告,編譯器會檢查出型態不符),然後呼叫a.compareTo(b),如果a物件==順序上小於==b物件,必須==傳回小於0==,若==順序上相等==則==傳回0==,若==順序上a大於b==則==傳回大於0==的值。
**所以只要在物件上實作Comparable的compareTo(比較方法):**
``Ex3``
```java=
import java.util.*;
public class Main
{
public static void main(String[] args) {
List<Person> P = new ArrayList<>();
P.add( new Person("Justin", 1000,false));
P.add(new Person("Monica", 500,true));
P.add( new Person("Irene", 200,false));
Collections.sort(P);
for(Person s :P)
System.out.println(s.money);
//Output
//200
//500
//1000
}
}
class Person implements Comparable<Person>
{
private String name ;
public int money;
private boolean marry;
public Person(String name ,int money,boolean marry)
{
this.name = name;
this.money = money;
this.marry = marry;
}
@Override
public int compareTo(Person other)
{
/*
if(this.money > other.money)
return 1;
if(this.money < other.money)
return -1;
return 0;
*/
//simplify
return this.money - other.money;
}
}
```
---
## Problem
**若在實際情況中無法修改物件或無法取的原始碼**,而==無法實作Comparable==呢?(e.g String為final物件無法被繼承)
Collections的sort()方法有另一個重載版本,可接受java.util.Comparator介面的實作物件,如果你使用這個版本,排序方式將根據Comparator的==compare()定義==來決定。
``Ex4``
```java=
import java.util.*;
public class Main
{
public static void main(String[] args) {
List<Person> P = new ArrayList<>();
P.add( new Person("Justin", 1000,false));
P.add(new Person("Monica", 500,true));
P.add( new Person("Irene", 200,false));
// Collections.sort(P,(a,b) -> (a.money - b.money));
Collections.sort(P,new Comparator<Person>(){
@Override
public int compare(Person a,Person b)
{
return a.money - b.money;
}
});
for(Person s :P)
System.out.println(s.money);
//Output
//200
//500
//1000
}
}
class Person
{
private String name ;
public int money;
private boolean marry;
public Person(String name ,int money,boolean marry)
{
this.name = name;
this.money = money;
this.marry = marry;
}
}
```
或是使用lambda表示式簡化:
``Ex5``
```java=
import java.util.*;
public class Main
{
public static void main(String[] args) {
List<Person> P = new ArrayList<>();
P.add( new Person("Justin", 1000,false));
P.add(new Person("Monica", 500,true));
P.add( new Person("Irene", 200,false));
Collections.sort(P,(a,b) -> (a.money - b.money));
for(Person s :P)
System.out.println(s.money);
//Output
//200
//500
//1000
}
}
class Person
{
private String name ;
public int money;
private boolean marry;
public Person(String name ,int money,boolean marry)
{
this.name = name;
this.money = money;
this.marry = marry;
}
}
```
`` Collections.sort(P,(a,b) -> (a.money - b.money)); ``
第二個Input Argument 已知為Compartor型態因而不必再給,input argument,(a,b)自行判斷其形態也省略,輸出為a.money - b.money
## Conclusion
當要對List進行sort,若為一般型態(e.g Integer,String...)則可以直接使用,但若型態為自定義class,則要實作comparator來給出誰跟誰比的定義.
## Reference
https://openhome.cc/Gossip/Java/ComparableComparator.html
###### tags: `java` `Sort`