似懂非懂 Comparable和 Comparator
在java中提供了两种排序方式:Comparable和 Comparator,它们两个看起来非常的相似,在不是很了解的情况下不知道如何使用,什么情况下使用哪个进行排序,接下来就看下它们的一个区别和使用方式:
Comparable
首先看下 Comparable,Comparable 它可以看成是一个排序接口,一个类实现了该接口,就表示该类本身具有排序的功能,如果对该类的集合或者数组进行排序,则可以使用 Collections.sort() 和 Arrays.sort() 进行排序而不用再指定额外的比较器;
此外,实现了该接口的类,也可以作为 SortedMap 和 SortedSet 的 key 也不用再指定额外的比较器, 但是,如果需要把实现了该接口的类当作 SortedMap 的 Key 或者 放入到 SortedSet 中,需要保证 e1.compareTo(e2) == 0 和 e1.equals(e2) 相等,
但是有一点需要注意的是:因为 e.equal(null) 会返回false,所以,当我们需要比较的对象为 null 的时候,应该抛出一个 空指针异常。
接下来看下 Comparable 接口的方法,该接口下只有一个方法:
public int compareTo(T o);
该接口返回一个 int 类型,有三种情况:
若 e1 > e2 则 e1.compateTo(e2) > 0,返回正数
若 e1 = e2 则 e1.compateTo(e2) = 0,返回0
若 e1 < e2 则 e1.compateTo(e2) < 0,返回负数
接下来看下如何使用:
首先定义一个类实现该接口,之后重写 compareTo() 方法,一般也需要重写 equal() 和 hashcode() 方法:
@Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor public class User implements Comparable<User> { private String name; private int age; private String job; @Override public int compareTo(User o) { return getName().compareTo(o.getName()); } @Override public int hashCode() { return getName().hashCode() * 31 + getAge(); } @Override public boolean equals(Object obj) { if (this == obj){ return true; } if (! (obj instanceof User)){ return false; } User u = (User)obj; return (getName().equals(u.getName())) && (getAge() == u.getAge()) && (getJob().equals(u.getJob())); } }
接下来就可以对 该类进行排序了:
首先创建该对象的一个集合:
User u1 = new User("zhangsan", 28, "C++"); User u2 = new User("zhangsan", 28, "C++"); User u3 = new User("wangwu", 22, "C"); User u4 = new User("xiaoliu", 26, "Python"); User u5 = new User("jiqjiq", 11, "Go"); System.out.println(u1.equals(u2)); // true System.out.println(u1.compareTo(u2) == 0); // true List<User> users = Lists.newArrayList(u1, u2, u3, u4, u5);
之后,可以使用 Collections.sort() 和 Arrays.sort() 进行排序,而不用再指定额外的比较器了:
System.out.println("排序之前..........."); users.forEach((u) -> System.out.println(u)); // 排序 Collections.sort(users); System.out.println("排序之后..."); users.forEach((u) -> System.out.println(u)); 结果: 排序之前........... User(name=zhangsan, age=28, job=C++) User(name=zhangsan, age=28, job=C++) User(name=wangwu, age=22, job=C) User(name=xiaoliu, age=26, job=Python) User(name=jiqjiq, age=11, job=Go) 排序之后... User(name=jiqjiq, age=11, job=Go) User(name=wangwu, age=22, job=C) User(name=xiaoliu, age=26, job=Python) User(name=zhangsan, age=28, job=C++) User(name=zhangsan, age=28, job=C++)
之后,还可以把这些对象放入到 SortedSet 中,就会自然对这些对象进行排序:
TreeSet<User> treeSet = new TreeSet<>(users); treeSet.forEach((user -> System.out.println(user))); 结果: User(name=jiqjiq, age=11, job=Go) User(name=wangwu, age=22, job=C) User(name=xiaoliu, age=26, job=Python) User(name=zhangsan, age=28, job=C++)
因为 Set 中没有重复元素,所有会过滤掉重复的元素。
在java的核心类库中,一些类已经实现该接口,所以可以直接对应它们进行排序,如 String , Integer 等:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence public final class Integer extends Number implements Comparable<Integer> List<String> strings = Lists.newArrayList("c", "e", "a", "b", "d"); Collections.sort(strings); List<Integer> integers = Lists.newArrayList(3, 2, 4, 1, 5); Collections.sort(integers);
Comparator
Comparator 可以把它看成是一个比较器接口,它是一个比较器,实现该接口的类本身没有比较的功能,只是用它去对其他的元素进行排序:
Comparator 接口有两个方法:
int compare(T o1, T o2); boolean equals(Object obj);
还有一些默认的方法,都是一些 java8 中的方法,
自定义一个比较器:
public class UserSortByName implements Comparator<User1> { @Override public int compare(User1 o1, User1 o2) { return o1.getName().compareTo(o2.getName()); } }
之后就可以使用该自定义的比较器对集合进行排序:
List<User1> users1 = Lists.newArrayList(u11, u21, u31, u41, u51); Collections.sort(users1, new UserSortByName());
当然,也可以不用自定义一个比较器,直接使用匿名类即可,如下:
// 排序 Collections.sort(users1, new Comparator<User1>() { @Override public int compare(User1 o1, User1 o2) { return o1.getName().compareTo(o2.getName()); } }); // lambda 表达式的写法: Collections.sort(users1, Comparator.comparing(User1::getName)); // 添加到 SortedSet 中 TreeSet<User1> treeSet1 = new TreeSet<>(new Comparator<User1>() { @Override public int compare(User1 o1, User1 o2) { return o1.getName().compareTo(o2.getName()); } }); treeSet1.addAll(users1); // lambda 表达式写法 TreeSet<User1> treeSet2 = new TreeSet<>(Comparator.comparing(User1::getName)); treeSet2.addAll(users1);
总结:
Comparable 它是一个排序接口,实现该接口的类本身具有排序的功能,可以直接使用 Collections.sort() 和 Arrays.sort() 进行排序而不用再指定额外的比较器;也可以直接放入到 SortedSet 和 SortedMap 中的保证其有序;
Comparator 它是一个比较器,实现该接口的类只能用其对其他对象进行排序;
Comparable 更多的像一个内部比较器,而 Comparator 更多的像一个外部比较器
![](/img/my/wx.png)
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
在docker for win中使用portainer管理容器
如何安装docker for win请参考我之前的文章《Docker在Win10下的安装和配置》 打开Kitematic图形管理工具,搜索portainer镜像 创建镜像,制定端口到宿主机9000端口(这个自定义) 宿主机直接访问http://localhost:9000即可 配置节点,我们选择远程连接方式 这里有个很隐晦的地方,就是主机的ip地址我们怎么填,在docker for win中我们需要先打开2375端口 从这里看是localhost,这个是宿主机,那么我们的portainer是在虚拟机里的,那么对于虚拟机来说如何访问宿主机的docker服务呢? 其实很简单,我们只需要填写docker.for.win.localhost:2375即可。 连接成功 我们可以方便的使用portainer进行容器的管理了。 在docker文档中可以找到:
- 下一篇
一个等效ping的EOS智能合约
这篇文章是为帮助EOS智能合约开发人员从初级到生产而发布的一系列帖子中的第一篇。有关本教程的完整代码,可以访问github存储库。 随着对EOS的所有兴奋而来的,对于大多数希望参与其中的开发人员仍然充满挑战的领域是开始使用智能合约。新开发人员通常需要克服两个障碍:获取工具和设置,并了解如何编写智能合约本身。 EOS智能合约是用C++编写的,并编译成Web Assembly。Dan Larimer选择C++来利用其类型和模板系统,这使得更安全的合约,并补充说,因为智能合约的运行时间很短,大多数内存问题都会消失。 配置 使用EOS的部分挑战是设置本地区块链。幸运的是,EOS为设置本地EOS环境提供了一些基础。对于本指南,我们将使用EOSIO Dawn 3.0。 该指南的摘要可以压缩为几个关键命令: $ git clone https://github.com/EOSIO/eos --recursive $ cd eos $ ./eosio_build.sh $ cd build && make install $ cd programs/nodeos $ ./nodeos ...
相关文章
文章评论
共有0条评论来说两句吧...