`
everlook
  • 浏览: 111593 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用TreeSet集合比较Comparable接口和Comparator接口的区别

    博客分类:
  • java
阅读更多
抄别人的文章,留着备忘。


TreeSet能够对集合中的对象排序,当TreeSet想集合中加入一个对象时,会把它插入到有序的对象序列中。那么TreeSet是如何排序呢?TreeSet支持两种排序方式:自然排序和客户化排序.在默认情况下TreeSet采用自然排序方式。
    先来介绍介绍什么是自然排序吧
  1、自然排序
   在JDK类库中,有一部分类实现了Comparable接口,如Integer Double和String等。
Comparable接口有一个comparTo(Object o)方法,它返回整数类型。对于表达式x.compareTo(y),如果返回值为0,则表示x和y相等,如果返回值大于0,则表示x大于y,如果返回值小于0,则表示x小于y.TreeSet集合调用对象的compareTo()方法比较集合中的大小,注意鸟 不是TreeSet调用它自己的comparTo()方法而是它调用集合中对象的comparTo()方法.TreeSet类本身并没有实现Comparable接口,然后进行升序排列,这种方式称为自然排序.
   有人可能要问TreeSet集合怎么给对象排序的按对象的什么排序的?
   下面简单总结一哈
    JDK类库中实现了Comparable接口的一些类的排序方式
类 BigDecimal BigInteger Byte Double Float Integer Long Short 排序方式是 按数字大小排序
类 Character是 按字符的Unicode值的数字大小排序
类 String是 按字符中字符的Unicode值排序


这里一定要灰常注意:使用自然排序时只能向集合中加入同类型的对象,并且这些对象的类必须实现Comparable接口
  下面来说说Comparable接口和Comparator接口的区别
Comparator位于包java.util下,而Comparable位于包   java.lang下

Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口)  此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

  比如你有一个Customer类 想让这个类的实例加入集合后自动就具有某种排序功能只要这些实例加入集合后 就会按照你给Customer对象设定的方式排序
代码:
Java代码 
package hang.jihe; 
 
import java.util.HashSet; 
import java.util.Set; 
 
public class Customer implements Comparable { 
    private String name; 
 
    private int age; 
 
    public Customer(String name, int age) { 
        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; 
    } 
 
    @Override 
    public boolean equals(Object obj) { 
        if (this == obj) 
            return true; 
        if (!(obj instanceof Customer)) 
            return false; 
        final Customer other = (Customer) obj; 
 
        if (this.name.equals(other.getName()) && this.age == other.getAge()) 
            return true; 
        else 
            return false; 
    } 
 
    public int compareTo(Object o) { 
        Customer other = (Customer) o; 
 
        // 先按照name属性排序 
        if (this.name.compareTo(other.getName()) > 0) 
            return 1; 
        if (this.name.compareTo(other.getName()) < 0) 
            return -1; 
 
        // 在按照age属性排序 
        if (this.age > other.getAge()) 
            return 1; 
        if (this.age < other.getAge()) 
            return -1; 
        return 0; 
    } 
 
    @Override 
    public int hashCode() { 
        int result; 
        result = (name == null ? 0 : name.hashCode()); 
        result = 29 * result + age; 
        return result; 
    } 



main方法的类
Java代码 
package hang.jihe; 
 
import java.util.Iterator; 
import java.util.Set; 
import java.util.TreeSet; 
 
public class CustomerTester { 
    public static void main(String[] args) { 
        Set<Customer> set = new TreeSet<Customer>(); 
        set.add(new Customer("Tom",15)); 
        set.add(new Customer("Tom",20)); 
        set.add(new Customer("Tom",15)); 
        set.add(new Customer("Mike",15)); 
         
        Iterator<Customer> it = set.iterator(); 
        while(it.hasNext()){ 
            Customer customer = it.next(); 
            System.out.println(customer.getName()+" "+customer.getAge()); 
        } 
    } 



Java代码 
//打印结果 
Mike 15 
Tom 15 
Tom 20 


有人会问 重写hashCode()方法 equals方法干嘛 别急 慢慢道来

实际上,所有实现 Comparable 的 Java 核心类都具有与 equals 一致的自然排序。java.math.BigDecimal 是个例外,它的自然排序将值相等但精确度不同的 BigDecimal 对象(比如 4.0 和 4.00)视为相等。为了保证TreeSet能正确地排序,要求Customer类的compareTo()方法与equals()方法按相同的规则比较两个Customer对象是否相等.也就是说,如果customer1.equals(customer2)为True,那么customer1.compareTo(customer2)为0。 既然重写了equals方法 就得重写hashCode()方法这个大家都知道
大家看一眼结果便知 这个按照升序排序的  年龄也是按照升序

  还有要注意哦,对于TreeSet中已经存在的Customer对象,如果修改了它们的name属性或age属性,则TreeSet不会对集合进行重新排序.例如下边的代码先把customer1和customer2 对象加入到TreeSet集合中,然后修改customer1的age属性
代码:
Java代码 
package hang.jihe; 
 
import java.util.Iterator; 
import java.util.Set; 
import java.util.TreeSet; 
 
public class TreeSetTest { 
    public static void main(String[] args) { 
        Set<Customer> set = new TreeSet<Customer>(); 
        Customer customer1 = new Customer("Tom",15); 
        Customer customer2 = new Customer("Tom",16); 
        set.add(customer1); 
        set.add(customer2); 
        //customer1.setAge(20);//修改customer1实例的age 
         
        Iterator<Customer> it=set.iterator(); 
        while(it.hasNext()){ 
            Customer customer=it.next(); 
            System.out.println(customer.getName()+" "+customer.getAge()); 
        } 
    } 


  上边我先把
Java代码 
customer1.setAge(20); 
这句注释掉
打印结果是:
Java代码 
Tom 15 
Tom 16 
这个是我们要的结果 name 和age都是按照升序排序的
然后我们把那句取消注释之后的打印结果是:
Java代码 
Tom 20 
Tom 16 

Tom 20如果按照升序应该在下边 但是却在上边 说明TreeSet没有给它重新排序哦在实际应用中Customer对象的name属性和age属性肯定应该是可以被修改的,因此不适合用TreeSet来排序。那大家也应该能想到最适合用TreeSet排序的就是不可变类了呗 比如Integer,Double,String等 所谓不可变类,是指当创建了这个类的实例后,就不允许修改它的属性值。大家以后用还是小心点好儿!

   客户化排序
   Comparator这个单词啥意思? 你知道不? 比较器的意思 学好英语还是挺好滴
   除了自然排序,TreeSet还支持客户化排序.java.util.Comparator<Type>接口提供具体的排序方式,<Type>指定被比较的对象的类型,Comparator有个compar(Type x,Type y)方法,用于比较两个对象的大小,当compare(x,y)大于0时表示x大于y,小于0表示x小于y
等于0表示x等于y
   来个例子如果希望TreeSet按照Customer对象的name属性进行降序排列,可以先创建一个实现Comparator接口的类
代码:
Java代码 
package hang.jihe; 
 
import java.util.Comparator; 
import java.util.Iterator; 
import java.util.Set; 
import java.util.TreeSet; 
 
public class CustomerComparator implements Comparator<Customer>{ 
 
    public int compare(Customer c1, Customer c2) { 
        if(c1.getName().compareTo(c2.getName())>0)return -1; 
        if(c1.getName().compareTo(c2.getName())<0)return 1; 
         
        return 0; 
    } 
     
    public static void main(String args[]){ 
        Set<Customer> set = new TreeSet<Customer>(new CustomerComparator()); 
         
        Customer customer1= new Customer("Tom",15); 
        Customer customer3= new Customer("Jack",16); 
        Customer customer2= new Customer("Mike",26); 
        set.add(customer1); 
        set.add(customer2); 
        set.add(customer3); 
         
        Iterator<Customer> it = set.iterator(); 
        while(it.hasNext()){ 
            Customer customer = it.next(); 
            System.out.println(customer.getName()+" "+customer.getAge()); 
        } 
    } 
 


  以上main方法在构造TreeSet的实例时,调用了它的TreeSet(Comparator comparator)构造方法.
Java代码 
Set<Customer> set = new TreeSet<Customer>(new CustomerComparator()); 
这是干甚? 其实就是指定一个比较器 TreeSet集合里边的对象按照这个比较器的规则进行排序 我把TreeSet类的这个构造方法搞上来看看就明白了 TreeSet里边有这样一个构造方法
TreeSet
public TreeSet(Comparator<? super E> comparator)构造一个新的空 TreeSet,它根据指定比较器进行排序。插入到该 set 的所有元素都必须能够由指定比较器进行相互比较:对于 set 中的任意两个元素 e1 和 e2,执行 comparator.compare(e1, e2) 都不得抛出 ClassCastException。如果用户试图将违反此约束的元素添加到 set 中,则 add 调用将抛出 ClassCastException。

参数:
comparator - 将用来对此 set 进行排序的比较器。如果该参数为 null,则使用元素的自然顺序。
  最后的打印结果是:
Java代码 
Tom 15 
Mike 26 
Jack 16 
是倒序 ...

  那你现在是不知道了comparable接口和comparable接口的区别了并且也能更好的使用TreeSet集合了
总结一下吧
单点解释吧:用自定义类实现Comparable接口,那么这个类就具有排序功能,Comparable和具体你要进行排序的类的实例邦定。而Comparator比较灵活,只需要通过构造方法指定一个比较器就行了实现它的自定义类仅仅定义了一种排序方式或排序规则。不言而喻,这种方式比较灵活。我们的要排序的类可以分别和多个实现Comparator接口的类绑定,从而达到可以按自己的意愿实现按多种方式排序的目的。Comparable——“静态绑定排序”,Comparator——“动态绑定排序”。

  在多墨迹一点 说说编写java类时应该养成一些好习惯吧
  一: 如果java类重新定义了equals方法,那么这个类也必须重新定义hashCode()方法,并且保证当两个对象用equals方法比较结果为true时,这两个对象的hashCode()方法的返回值相等.

  二:如果java类实现了Comparable接口,那么这个类应该从新定义compareTo() equals() 和hashCode()方法,保证compareTo()和equals()方法采用相同的比较规则来比较两个对象是否相等,并且保证当两个对象用equals()方法比较的结果为true时,这两个对象的hashCode()方法的返回值相等.
   HashSet和HashMap具有较好的性能,是Set和Map首选实现类,只有在需要排序的场合,才考虑使用TreeSet和TreeMap. LinkedList 和 ArrayList各有优缺点,如果经常对元素执行插入和删除操作,那么可以用LinkedList,如果经常随机访问元素,那么可以用ArrayList.
分享到:
评论

相关推荐

    【IT十八掌徐培成】Java基础第12天-02.TreeSet实现与Comparable接口.zip

    【IT十八掌徐培成】Java基础第12天-02.TreeSet实现与Comparable接口.zip

    TreeSet集合用法

    介绍TreeSet集合用法,向TreeSet集合中添加类的对象,此类需实现Comparable接口,有实例,供需要的朋友下载学习。

    javaTreeSet实现图书管理系统

    图书馆管理 1.描述一个图书馆 2.进书,借书卡办理 3.借书,还书 4.查询某书的借出记录 5.查询借书卡的借出记录 6.显示图书列表(按借出次数排序)

    java集合-TreeSet的使用

    TreeSet 是 Java 中的一个集合类,它实现了 SortedSet 接口,并且使用红黑树作为底层数据结构。TreeSet 具有以下主要特点: 排序性:TreeSet 中的元素是有序的,默认按照元素的自然顺序进行排序。或者,可以在创建 ...

    java泛型 用了treeset

    使用TreeSet和Comparator,编写TreeSetTest2类,要求对TreeSet中的元素1-元素10进行排列,排序逻辑为奇数在前偶数在后,奇数按照升序排列,偶数按照降序排列。 如果需要的话可以下载,有写成文章的。有写了一点中文...

    Java 集合方面的面试题

    什么是 Comparable 和 Comparator 接口?它们有什么区别? 如何使用 ConcurrentHashMap 类来实现线程安全的映射? 如何避免在多线程环境下对同一集合的并发修改? 如何使用 PriorityQueue 类实现一个最小堆? 如何...

    day05-迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类 - 副本.md

    这是为了方便大家了解集合类的相关知识所找的一个MarkDown文档,读者可以通过阅读了解各种子类集合的实现原理,红黑树的实现也会有所介绍.

    Java集合框架Set接口.pdf

    Set接口的实现类包括HashSet、LinkedHashSet和TreeSet。 HashSet是基于哈希表实现的Set集合,它不保证集合中元素的顺序。由于哈希表的实现机制,HashSet的添加、删除和查找操作都具有很好的性能,时间复杂度为O(1)。...

    Java基础知识点.html

    哈希值 LinkedHashSet TreeSet 自然排序Comparable 比较器排序Comparator Set集合 并发修改异常 LinkedList集合 ArrayList集合 List集合 Collection集合概述 冒泡排序 Object 异常 Math 包装类 Calendar类 ...

    Java集合框架完整说明便于了解集合

    java集合在日常开发中经常用到,对基础的掌握尤其重要,其中List,Set,Map的作用以及使用的场景和分类描述,其中Arraylist 与 LinkedList 区别,HashSet与TreeSet与LinkedHashSet对⽐,LinkedHashMap和HashMap,...

    java排序代码

    定制排序:在创建TreeSet集合对象时,并提供一个Comparator接口实现类对象与该TreeSet集合关联, 由Comparator实现类对象负责集合元素的排序逻辑。 // 自定义比较器 class MyTreeSetCompartor implements...

    java 集合框架(TreeSet练习)

    毕向东Java基础视频教程-集合框架(TreeSet练习).

    day18-集合-中(HashSet&TreeSet&比较器).zip

    day18-集合-中(HashSet&TreeSet&比较器).zip

    TreeSet 不用自然排序自己做比较器

    Comparator&lt;String&gt; com = new Comparator&lt;String&gt;(){ public int compare(String o1,String o2) { return o1.length()-o2.length(); } }; TreeSet ts = new TreeSet(com); ts.add("string"); ts.add(...

    排序之HashSet和TreeSet的区别

    NULL 博文链接:https://elvin-chu.iteye.com/blog/1942033

    Java期末复习-类集框架

    List接口、ArrayList类、Vector类、栈操作类Stack、链表操作类LinkList、队列操作接口Queue、Set接口、HashSet类、TreeSet类、SortedSet接口 双值操作接口Map(key-&gt;value)及其子接口、子类: SortedMap接口、HashMap...

    Java集合框架总结:TreeSet类的排序问题

    java提供了一个Comparable接口,该接口里定义了一个compareTo(Objectobj)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现了该接口的类的对象就可以比较大小。当一个对象调用该方法与另一个对象进行...

    详解Java中HashSet和TreeSet的区别

    主要介绍了详解Java中HashSet和TreeSet的区别的相关资料,需要的朋友可以参考下

    HashSet和TreeSet_围墙之外

    HashSet和TreeSet_围墙之外.rar

    Java数据结构--13.Java8数据结构TreeSet.pdf

    * 元素由它们的⾃然 Comparable 排序,或者通过⼀个由顺序 set 创建时特别提供的 * Comparator。这个 set 的迭代器将会以递增元素顺序横穿 set。提供多个额外的操作来⽀持排 * 序。(这个接⼝与 SortedMap 的 set ...

Global site tag (gtag.js) - Google Analytics