http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt159
http://blog.csdn.net/cuiyong314/article/details/7570513
1. Comparator 和 Comparable 相同的地方 他们都是java的一个接口, 并且是用来对自定义的class比较大小的, 什么是自定义class: 如 public class Person{ String name; int age }. 当我们有这么一个personList,里面包含了person1, person2, persion3....., 我们用Collections.sort( personList ), 是得不到预期的结果的. 这时肯定有人要问, 那为什么可以排序一个字符串list呢: 如 StringList{"hello1" , "hello3" , "hello2"}, Collections.sort( stringList ) 能够得到正确的排序, 那是因为 String 这个对象已经帮我们实现了 Comparable接口 , 所以我们的 Person 如果想排序, 也要实现一个比较器。 2. Comparator 和 Comparable 的区别 Comparable Comparable 定义在 Person类的内部: public class Persion implements Comparable {..比较Person的大小..}, 因为已经实现了比较器,那么我们的Person现在是一个可以比较大小的对象了,它的比较功能和String完全一样,可以随时随地的拿来比较大小,因为Person现在自身就是有大小之分的。Collections.sort(personList)可以得到正确的结果。 Comparator Comparator 是定义在Person的外部的, 此时我们的Person类的结构不需要有任何变化,如 public class Person{ String name; int age }, 然后我们另外定义一个比较器: public PersonComparator implements Comparator() {..比较Person的大小..}, 在PersonComparator里面实现了怎么比较两个Person的大小. 所以,用这种方法,当我们要对一个 personList进行排序的时候, 我们除了了要传递personList过去, 还需要把PersonComparator传递过去,因为怎么比较Person的大小是在PersonComparator里面实现的, 如: Collections.sort( personList , new PersonComparator() ). 3. Comparator 和 Comparable 的实例 Comparable: 实现Comparable接口要覆盖compareTo方法, 在compareTo方法里面实现比较: public class Person implements Comparable { String name; int age public int compareTo(Person another) { int i = 0; i = name.compareTo(another.name); // 使用字符串的比较 if(i == 0) { // 如果名字一样,比较年龄, 返回比较年龄结果 return age - another.age; } else { return i; // 名字不一样, 返回比较名字的结果. } } } 这时我们可以直接用 Collections.sort( personList ) 对其排序了. Comparator: 实现Comparator需要覆盖 compare 方法: public class Person{ String name; int age } class PersonComparator implements Comparator { public int compare(Person one, Person another) { int i = 0; i = one.name.compareTo(another.name); // 使用字符串的比较 if(i == 0) { // 如果名字一样,比较年龄,返回比较年龄结果 return one.age - another.age; } else { return i; // 名字不一样, 返回比较名字的结果. } } } Collections.sort( personList , new PersonComparator()) 可以对其排序 4:总结 两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码, 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
=================================================
分类:
JAVA Comparable 和Comparator用法--转载
ThreeSet可以或许对凑集中的对象排序,当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接口的一些类的排序体式格式
这里必然要灰常重视:应用天然排序时只能向凑集中参加同类型的对象,并且这些对象的类必须实现Comparable接口
下面来说说Comparable接口和Comparator接口的差别
Comparator位于包java.util下,而Comparable位于包 java.lang下
Comparable 是一个对象本身就已经支撑自斗劲所须要实现的接口(如 String、Integer 本身就可以完成斗劲大小操纵,已经实现了Comparable接口) 此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的天然排序,类的 compareTo 办法被称为它的天然斗劲办法。
比如你有一个Customer类 想让这个类的实例参加凑集后主动就具有某种排序功能只要这些实例参加凑集后 就会遵守你给Customer对象设定的体式格式排序
代码:
main办法的类
有人会问 重写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属性
代码:
上边我先把
这句注释掉
打印成果是:
这个是我们要的成果 name 和age都是遵守升序排序的
然后我们把那句作废注释之后的打印成果是:
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接口的类
代码:
以上main办法在机关TreeSet的实例时,调用了它的TreeSet(Comparator comparator)机关办法.
这是干甚? 其实就是指定一个斗劲器 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,则应用元素的天然次序。
最后的打印成果是:
是倒序 ...
那你如今是不知道了comparable接口和comparable接口的差别了并且也能更好的应用TreeSet凑集了
总结一下吧
单点申明吧:用自定义类实现Comparable接口,那么这个类就具有排序功能,Comparable和具体你要进行排序的类的实例邦定。而Comparator斗劲灵活,只须要经由过程机关办法指定一个斗劲器就行了实现它的自定义类仅仅定义了一种排序体式格式或排序规矩。不问可知,这种体式格式斗劲灵活。我们的要排序的类可以分别和多个实现Comparator接口的类绑定,从而达到可以按本身的意愿实现按多种体式格式排序的目标。Comparable&#8212;&#8212;&#8220;静态绑定排序&#8221;,Comparator&#8212;&#8212;&#8220;动态绑定排序&#8221;。
在多墨迹一点 说说编写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.
ThreeSet可以或许对凑集中的对象排序,当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接口的一些类的排序体式格式
这里必然要灰常重视:应用天然排序时只能向凑集中参加同类型的对象,并且这些对象的类必须实现Comparable接口
下面来说说Comparable接口和Comparator接口的差别
Comparator位于包java.util下,而Comparable位于包 java.lang下
Comparable 是一个对象本身就已经支撑自斗劲所须要实现的接口(如 String、Integer 本身就可以完成斗劲大小操纵,已经实现了Comparable接口) 此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的天然排序,类的 compareTo 办法被称为它的天然斗劲办法。
比如你有一个Customer类 想让这个类的实例参加凑集后主动就具有某种排序功能只要这些实例参加凑集后 就会遵守你给Customer对象设定的体式格式排序
代码:
main办法的类
有人会问 重写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属性
代码:
上边我先把
这句注释掉
打印成果是:
这个是我们要的成果 name 和age都是遵守升序排序的
然后我们把那句作废注释之后的打印成果是:
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接口的类
代码:
以上main办法在机关TreeSet的实例时,调用了它的TreeSet(Comparator comparator)机关办法.
这是干甚? 其实就是指定一个斗劲器 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,则应用元素的天然次序。
最后的打印成果是:
是倒序 ...
那你如今是不知道了comparable接口和comparable接口的差别了并且也能更好的应用TreeSet凑集了
总结一下吧
单点申明吧:用自定义类实现Comparable接口,那么这个类就具有排序功能,Comparable和具体你要进行排序的类的实例邦定。而Comparator斗劲灵活,只须要经由过程机关办法指定一个斗劲器就行了实现它的自定义类仅仅定义了一种排序体式格式或排序规矩。不问可知,这种体式格式斗劲灵活。我们的要排序的类可以分别和多个实现Comparator接口的类绑定,从而达到可以按本身的意愿实现按多种体式格式排序的目标。Comparable&#8212;&#8212;&#8220;静态绑定排序&#8221;,Comparator&#8212;&#8212;&#8220;动态绑定排序&#8221;。
在多墨迹一点 说说编写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.
先来介绍介绍什么是天然排序吧
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 static void main(String[] args) {
- Set<Customer> set = new HashSet<Customer>();
- Customer customer1 = new Customer("Tom", 15);
- Customer customer2 = new Customer("Tom", 15);
- set.add(customer1);
- set.add(customer2);
- System.out.println(set.size());
- }
- 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
然后我们把那句作废注释之后的打印成果是:
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
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&#8212;&#8212;&#8220;静态绑定排序&#8221;,Comparator&#8212;&#8212;&#8220;动态绑定排序&#8221;。
在多墨迹一点 说说编写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.
ThreeSet可以或许对凑集中的对象排序,当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对象设定的体式格式排序
代码:
- 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 static void main(String[] args) {
- Set<Customer> set = new HashSet<Customer>();
- Customer customer1 = new Customer("Tom", 15);
- Customer customer2 = new Customer("Tom", 15);
- set.add(customer1);
- set.add(customer2);
- System.out.println(set.size());
- }
- 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办法的类
- 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());
- }
- }
- }
- //打印成果
- 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属性
代码:
- 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());
- }
- }
- }
上边我先把
- customer1.setAge(20);
打印成果是:
- Tom 15
- Tom 16
然后我们把那句作废注释之后的打印成果是:
- 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接口的类
代码:
- 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)机关办法.
- Set<Customer> set = new TreeSet<Customer>(new CustomerComparator());
TreeSet
public TreeSet(Comparator<? super E> comparator)机关一个新的空 TreeSet,它按照指定斗劲器进行排序。插入到该 set 的所有元素都必须可以或许由指定斗劲器进行彼此斗劲:对于 set 中的随便率性两个元素 e1 和 e2,履行 comparator.compare(e1, e2) 都不得抛出 ClassCastException。若是用户试图将违背此束缚的元素添加到 set 中,则 add 调用将抛出 ClassCastException。
参数:
comparator - 将用来对此 set 进行排序的斗劲器。若是该参数为 null,则应用元素的天然次序。
最后的打印成果是:
- Tom 15
- Mike 26
- Jack 16
那你如今是不知道了comparable接口和comparable接口的差别了并且也能更好的应用TreeSet凑集了
总结一下吧
单点申明吧:用自定义类实现Comparable接口,那么这个类就具有排序功能,Comparable和具体你要进行排序的类的实例邦定。而Comparator斗劲灵活,只须要经由过程机关办法指定一个斗劲器就行了实现它的自定义类仅仅定义了一种排序体式格式或排序规矩。不问可知,这种体式格式斗劲灵活。我们的要排序的类可以分别和多个实现Comparator接口的类绑定,从而达到可以按本身的意愿实现按多种体式格式排序的目标。Comparable&#8212;&#8212;&#8220;静态绑定排序&#8221;,Comparator&#8212;&#8212;&#8220;动态绑定排序&#8221;。
在多墨迹一点 说说编写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.