在之前的文章我們介紹了一下 Java 中的 集合框架中的Collection 的子接口 List的 增刪改查和與數組間相互轉換的方法,本章我們來看一下 Java 集合框架中的Collection 的子接口 List 的另外一些方法。
我們在使用集合的時候難免會對其中的元素進行排序,因為 Set 集合本身是無序的,所以本章將着重講解 List 集合,如下:
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 import java.util.Random; 5 6 /** 7 * 排序集合元素 8 * 排序集合使用的是集合的工具類 Collections 的靜態方法 sort 9 * 排序僅能對 List 集合進行,因為 Set 部分實現類是無序的 10 * */ 11 public class Main { 12 public static void main(String[] args) { 13 List<Integer> list = new ArrayList<Integer>(); 14 Random random = new Random(); 15 for(int i=0;i<10;i++){ 16 list.add(random.nextInt(100)); 17 } 18 System.out.println(list); // [49, 24, 29, 59, 56, 1, 1, 5, 49, 60] 19 20 Collections.sort(list); 21 System.out.println(list); // [1, 1, 5, 24, 29, 49, 49, 56, 59, 60] 22 } 23 }
在上面的代碼中,我們隨機生成了一些正數並添加到 List 集合中,我們通過 sort 方法,系統變自動按照自然數的排列方法為我們做好了排序,很是方便,那如果 List 中使我們自己定義的內容,比如說一個類,那該如何排序呢,如下:
import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 排序集合元素 * 排序集合使用的是集合的工具類 Collections 的靜態方法 sort * 排序僅能對 List 集合進行,因為 Set 部分實現類是無序的 */ public class Main { public static void main(String[] args) { List<Point> list = new ArrayList<Point>(); list.add(new Point(1, 2)); list.add(new Point(2, 3)); list.add(new Point(4, 2)); list.add(new Point(2, 5)); list.add(new Point(9, 3)); list.add(new Point(7, 1)); System.out.println(list); // [(1, 2), (2, 3), (4, 2), (2, 5), (9, 3), (7, 1)] // Collections.sort(list); // 編譯錯誤,不知道 Point 排序規則 /** * sort 方法要求集合必須實現 Comparable 接口 * 該接口用於規定實現類事可以比較的 * 其中一個 compareTo 方法時用來定義比較大小的規則 * */ Collections.sort(list); System.out.println(list); // [(1, 2), (2, 3), (4, 2), (2, 5), (7, 1), (9, 3)] } } class Point implements Comparable<Point> { // 定義為泛型 T 類型 private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } @Override public String toString() { return "(" + x + ", " + y + ")"; } /** * 當實現了 Comparable 接口后,需要重寫下面的方法 * 該方法的作用是定義當前對象與給定參數對象比較大小的規則 * 返回值為一個 int 值,該值表示大小關係 * 它不關注具體的取值是多少,而關注的是取值範圍 * 當返回值 >0 時:當前對象不參數對象大 * 當返回值 <0 時:當前對象比參數對象小 * 當返回值 =0 時:兩個對象相等 */ @Override public int compareTo(Point o) { /** * 比較規則,點到原點的距離長的打 * */ int len = this.x * this.x + this.y * this.y; int olen = o.x * o.x + o.y * o.y; return len - olen; } }
在上面的代碼中,我們跟之前一樣定義了一個 Point 類,然後實例化后存入 list 集合中,如果我們相對 Point 進行排序,如果直接調用 sort 方法會報錯,這是由於編譯器不知道我們定義的 Point 類的排序規則,所以我們需要通過接口 Comparable 接口來自定義排序規則,如下圖:
我們可以通過坐標系中點到原點的距離來判斷 Point 的大小,即 x*x+y*y 的大小,然後通過重寫 compareTo 方法來實現 sort 。
實際上雖然能實現,但是並不理想,為了實現一個 sort 方法,要求我們的集合元素必須實現 Comparable 接口並且定義比較規則,這種我們想使用某個功能,而它要求我們修改程序的現象稱為“侵入性”。修改的代碼越多,侵入性越強,越不利於程序的擴展。
我們再來看一下下面的排序:
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 5 public class Main { 6 public static void main(String[] args) { 7 List<String> list1 = new ArrayList<String>(); 8 list1.add("Java"); 9 list1.add("c++"); 10 list1.add("Python"); 11 list1.add("PHP"); 12 Collections.sort(list1); 13 System.out.println(list1); // [Java, PHP, Python, c++] 14 15 List<String> list2 = new ArrayList<String>(); 16 list2.add("孫悟空"); 17 list2.add("豬八戒"); 18 list2.add("唐僧"); 19 list2.add("六小齡童"); 20 Collections.sort(list2); 21 System.out.println(list2); // [六小齡童, 唐僧, 孫悟空, 豬八戒] 22 23 } 24 }
在上面的排序中,當我們對字母或漢字進行排序時,其實是比的第一個字的 Unicode 碼,那如果我們不使用 Comparable 的接口該如何自定義我們想要的實現規則呢?比如根據字符串的長度來進行排序,其實 sort 有一個額外的重載方法來實現我們想要的結果,如下:
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Comparator; 4 import java.util.List; 5 6 public class Main { 7 public static void main(String[] args) { 8 /** 9 * 重載的 sort 方法要求傳入一個額外的比較器 10 * 該方法不再要求集合元素必須實現 Comparable 接口 11 * 並且不再使用集合元素資深的比較規則排序了 12 * 而是根據給定的這個額外的比較器的比較規則對集合元素進行排序 13 * 實際開發中也推薦使用這種方式進行集合元素排序 14 * 若集合元素是自定義的 15 * 創建比較器時推薦使用匿名內部類的形式 16 */ 17 List<String> list1 = new ArrayList<String>(); 18 list1.add("Java"); 19 list1.add("c++"); 20 list1.add("Python"); 21 list1.add("PHP"); 22 MyComparator myComparator1 = new MyComparator(); 23 Collections.sort(list1, myComparator1); // 重載 sort 24 System.out.println(list1); // [c++, PHP, Java, Python] 25 26 List<String> list2 = new ArrayList<String>(); 27 list2.add("孫悟空"); 28 list2.add("豬八戒"); 29 list2.add("唐僧"); 30 list2.add("六小齡童"); 31 // 匿名內部類形式創建 32 Comparator<String> myComparator2 = new Comparator<String>() { 33 @Override 34 public int compare(String o1, String o2) { 35 return o1.length() - o2.length(); 36 } 37 }; 38 Collections.sort(list2, myComparator2); // 重載 sort 39 System.out.println(list2); // [唐僧, 孫悟空, 豬八戒, 六小齡童] 40 41 } 42 } 43 44 /** 45 * 定義一個額外的比較器 46 * 該方法用來定義 o1 和 o2 的比較 47 * 若返回值 >0:o1>o2 48 * 若返回值 <0:o1<o2 49 * 若返回值 =0:兩個對象相等 50 */ 51 class MyComparator implements Comparator<String> { 52 @Override 53 public int compare(String o1, String o2) { 54 /** 55 * 字符串中字符多的大 56 * */ 57 return o1.length() - o2.length(); 58 } 59 }
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※想知道最厲害的網頁設計公司"嚨底家"!
※幫你省時又省力,新北清潔一流服務好口碑
※別再煩惱如何寫文案,掌握八大原則!
特斯拉(Tesla)高調宣布鋰電池儲能系統,其中針對企業用戶的「Powerpack」,100 度電售價 25,000 美元,已將平均儲能成本拉低到相當驚人的每度電 250 美元,一般認為若平均儲能成本降到每度電 100 美元,將引爆能源儲存革命,特斯拉挾 GigaFactory 的威力,正全速逼近這個目標,不過,卻有一個小型新創事業,認為現在就可以做到。 這家新創事業 FreeWire 初期募資金額不過 42.5 萬美元,加上美國海軍資助 50 萬美元,如何能超越家大業大的特斯拉?其實原理也不難,就是採用二手電池。 FreeWire 、日產(Nissan)與 NEC 合資的汽車能源供應公司(Automotive Energy Supply Corporation,AESC)合作,AESC 是僅次於 Panasonic,全球第二大車用鋰電池供應商,市佔率達 21%,2014 年銷售最佳的電動車是 Nissan Leaf,其電池正是由 AESC 供應,Nissan 每個月都會測試電池,每六個月就汰換效能已經衰退的鋰電池,數量以千計,對 Nissan 來說庫存這些二線電池是個麻煩,但這些電池的效能或許已經不不敷電動車所需,拿來做為能源儲存用途卻還很有用。 於是,FreeWire 以新電池六分之一的價格取得這些二手電池,第一步,是取之於電動車用之於電動車,將這些二手電池組裝成總容量 48 度電的行動充電車,專供電動車在本來沒有設置充電座的停車場、機場、企業廠區等處充電,行動充電車可以推到停車場任何一個停車格,幫電動車充電,如此一來,停車場可以省下設置大量充電座的成本,卻能提供身為少數的電動車主充電服務,而這些二手電池在每天充放電循環 2 次的情況下,還可以有 5 年的壽命。 