隨筆 - 0, 文章 - 2, 評(píng)論 - 0, 引用 - 0
          數(shù)據(jù)加載中……

          java中的Comparable與Comparator

                 以前一直對(duì)Comparable與Comparator的區(qū)別比較模糊,今天抽空好好的了解了下,發(fā)現(xiàn)收獲蠻大的,所以來(lái)跟大家分享下,如果有不對(duì)的地方還請(qǐng)指正。
                 先來(lái)看看這2個(gè)接口在jdk API種的解釋?zhuān)?br />              Comparable:此接口強(qiáng)行對(duì)實(shí)現(xiàn)它的每個(gè)類(lèi)的對(duì)象進(jìn)行整體排序。這種排序被稱(chēng)為類(lèi)的自然排序,類(lèi)的 compareTo 方法被稱(chēng)為它的自然比較方法。
          實(shí)現(xiàn)此接口的對(duì)象列表(和數(shù)組)可以通過(guò) Collections.sort(和 Arrays.sort)進(jìn)行自動(dòng)排序。實(shí)現(xiàn)此接口的對(duì)象可以用作有序映射中的鍵或有序集合中的元素,無(wú)需指定比較器。
                        Comparator:強(qiáng)行對(duì)某個(gè)對(duì)象 collection 進(jìn)行整體排序 的比較函數(shù)。可以將 Comparator 傳遞給 sort 方法(如 Collections.sort 或 Arrays.sort),從而允許在排序順序上實(shí)現(xiàn)精確控制。還可以使用 Comparator 來(lái)控制某些數(shù)據(jù)結(jié)構(gòu)(如有序 set或有序映射)的順序,或者為那些沒(méi)有自然順序的對(duì)象 collection 提供排序。
                        實(shí)現(xiàn)此接口的對(duì)象可以用作有序映射中的鍵或有序集合中的元素,無(wú)需指定比較器。從這句話可以看出我們之所以可以對(duì)數(shù)字或者字母進(jìn)行排序而不需制定比較器,是因?yàn)樵贘DK中他們已經(jīng)實(shí)現(xiàn)了Comparable接口,所以通過(guò)Collections.sort和 Arrays.sort方法可以給他們按自然順序排序,當(dāng)我們要對(duì)一個(gè)自定義對(duì)象進(jìn)行排序的時(shí)候,也可以實(shí)現(xiàn)Comparable接口,實(shí)現(xiàn)它的compareTo方法。
                    
          1 @Override
          2     public int compareTo(User user) {
          3         if(this == null || user == null || this.getAge() > user.getAge())
          4             return 1;
          5         if(this.getAge() < user.getAge())
          6             return -1;
          7         return 0;
          8     }
               如果該對(duì)象小于、等于或大于指定對(duì)象,則分別返回負(fù)整數(shù)、零或正整數(shù),可以通過(guò)返回的值來(lái)控制對(duì)象在集合的位置,可以按年齡的小到大排序,也可以按年齡的大到小排序。
               如果要用Comparator接口來(lái)實(shí)現(xiàn)對(duì)象在集合中的排序,直接在對(duì)象中實(shí)現(xiàn)Comparator接口是不起作用的(針對(duì)TreeSet,下文中一樣,其它的集合類(lèi)還沒(méi)發(fā)現(xiàn)可以在對(duì)象中實(shí)現(xiàn)Comparator來(lái)進(jìn)行排序),需要另外新建一個(gè)類(lèi)實(shí)現(xiàn)Comparator接口,然后通過(guò)集合的構(gòu)造函數(shù)傳到集合中,才會(huì)起作用,直接看TreeSet的源代碼吧。
           1 int cmp;
           2         Entry<K,V> parent;
           3         // split comparator and comparable paths
           4         Comparator<? super K> cpr = comparator;
           5         if (cpr != null) {
           6             do {
           7                 parent = t;
           8                 cmp = cpr.compare(key, t.key);
           9                 if (cmp < 0)
          10                     t = t.left;
          11                 else if (cmp > 0)
          12                     t = t.right;
          13                 else
          14                     return t.setValue(value);
          15             } while (t != null);
          16         }
          17         else {
          18             if (key == null)
          19                 throw new NullPointerException();
          20             Comparable<? super K> k = (Comparable<? super K>) key;
          21             do {
          22                 parent = t;
          23                 cmp = k.compareTo(t.key);
          24                 if (cmp < 0)
          25                     t = t.left;
          26                 else if (cmp > 0)
          27                     t = t.right;
          28                 else
          29                     return t.setValue(value);
          30             } while (t != null);
          31         }
          32         Entry<K,V> e = new Entry<K,V>(key, value, parent);
          33         if (cmp < 0)
          34             parent.left = e;
          35         else
          36             parent.right = e;
          37         fixAfterInsertion(e);
          38         size++;
          39         modCount++;
          40         return null;
          comparator是在構(gòu)造TreeSet對(duì)象的時(shí)候傳進(jìn)去的,所以如果comparator為null,它就會(huì)按照Comparable排序,如果對(duì)象沒(méi)有實(shí)現(xiàn)Comparable接口,就會(huì)拋出異常,所以到現(xiàn)在為止,我還沒(méi)發(fā)現(xiàn)直接在對(duì)象中實(shí)現(xiàn)comparator接口可以排序的。看完這段代碼我們還可以發(fā)現(xiàn)如果對(duì)象沒(méi)有實(shí)現(xiàn)Comparable接口或者沒(méi)有通過(guò)構(gòu)造一個(gè)以comparator為排序的集合,是不能在TreeSet或TreeMap中使用的(實(shí)際TreeSet就是通過(guò)TreeMap實(shí)現(xiàn)的,不了解的可以看TreeSet的源代碼),最多只能添加一個(gè)對(duì)象root。
           1 Entry<K,V> t = root;
           2         if (t == null) {
           3         // TBD:
           4         // 5045147: (coll) Adding null to an empty TreeSet should
           5         // throw NullPointerException
           6         //
           7         // compare(key, key); // type check
           8             root = new Entry<K,V>(key, value, null);
           9             size = 1;
          10             modCount++;
          11             return null;
          12         }
              comparator的用處在于可以通過(guò)不同的comparator實(shí)現(xiàn)類(lèi),在不通的條件下對(duì)在集合中的對(duì)象按不同的順序進(jìn)行排序,這樣充分利用了java的多態(tài),也讓我們?cè)诰幊痰倪^(guò)程中能很好的解耦。
              利用Arrays.sort(T[] a, Comparator<? super T> c)可以對(duì)數(shù)組進(jìn)行排序,利用Collections.sort(List<T> list, Comparator<? super T> c) 可以對(duì)實(shí)現(xiàn)了list接口的集合進(jìn)行排序,如果需要對(duì)Set進(jìn)行排序,可以先把Set轉(zhuǎn)換成ArrayList,然后再進(jìn)行排序。
           1         Set<User> users = new TreeSet<User>(new UserComparator());
           2         User user = new User();
           3         user.setAge(24);
           4         user.setName("wenbo");
           5         users.add(user);
           6         User user1 = new User();
           7         user1.setAge(23);
           8         user1.setName("wenbo1");
           9         users.add(user1);
          10         List<User> useList = new ArrayList<User>(users);
          11         Collections.sort(useList,new UserMaxComparator());
               通過(guò)上面的分析,不知道大家有沒(méi)有理解這2個(gè)接口,我認(rèn)為如果需要對(duì)一個(gè)對(duì)象進(jìn)行排序,建議使用comparator接口,因?yàn)樗`活,或許效率更高。
             











          posted on 2011-11-26 17:44 樂(lè)隨心動(dòng) 閱讀(376) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): java基礎(chǔ)


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 进贤县| 清镇市| 喀喇沁旗| 舒城县| 正镶白旗| 昭苏县| 和林格尔县| 乌拉特后旗| 得荣县| 剑川县| 临漳县| 土默特左旗| 建德市| 交城县| 讷河市| 邹平县| 齐河县| 漳浦县| 安国市| 达尔| 康马县| 武清区| 长武县| 翁源县| 辽宁省| 边坝县| 龙口市| 阿坝| 红安县| 吉木乃县| 安龙县| 太原市| 丰都县| 香港 | 威信县| 景宁| 三亚市| 甘孜| 巴彦县| 通州市| 眉山市|