一、需求

假设现在有个如此的需求:需要对一个这样的雇员列表进行排序,排序规则如下:

1、首先级别最高的排在前面,

2、如果级别相等,那么按工资排序,工资高的排在前面,

3、如果工资相当则按入职年数排序,入职时间最长的排在前面。

雇员对象包含级别、工资和入职年份,代码如下:

  1. /**
  2. * 雇员
  3. */
  4. class Employee {
  5. /**
  6. * ID
  7. */
  8. public int id;
  9. /**
  10. * 级别
  11. */
  12. public int level;
  13. /**
  14. * 工资
  15. */
  16. public int salary;
  17. /**
  18. * 入职年数
  19. */
  20. public int year;
  21. public int getId() {
  22. return id;
  23. }
  24. public void setId(int id) {
  25. this.id = id;
  26. }
  27. public int getLevel() {
  28. return level;
  29. }
  30. public void setLevel(int level) {
  31. this.level = level;
  32. }
  33. public int getSalary() {
  34. return salary;
  35. }
  36. public void setSalary(int salary) {
  37. this.salary = salary;
  38. }
  39. public int getYear() {
  40. return year;
  41. }
  42. public void setYear(int year) {
  43. this.year = year;
  44. }
  45. public Employee(int id, int level, int salary, int year) {
  46. this.id = id;
  47. this.level = level;
  48. this.salary = salary;
  49. this.year = year;
  50. }
  51. }

二、实现Comparator接口

这里我们实现java.util.Comparator接口,用于对雇员列表进行排序,代码如下:

  1. private Comparator<Employee> comparator = new Comparator<Employee>() {
  2. @Override
  3. public int compare(Employee employee1, Employee employee2) {
  4. int cr = 0;
  5. //按级别降序排列
  6. int a = employee2.getLevel() - employee1.getLevel();
  7. if (a != 0) {
  8. cr = (a > 0) ? 3 : -1;
  9. } else {
  10. //按薪水降序排列
  11. a = employee2.getSalary() - employee1.getSalary();
  12. if (a != 0) {
  13. cr = (a > 0) ? 2 : -2;
  14. } else {
  15. //按入职年数降序排列
  16. a = employee2.getYear() - employee1.getYear();
  17. if (a != 0) {
  18. cr = (a > 0) ? 1 : -3;
  19. }
  20. }
  21. }
  22. return cr;
  23. }
  24. };

三、验证排序结果

下面用一个单元测试,来验证排序结果是否正确

  1. @Test
  2. public void sortTest() throws Exception {
  3. List<Employee> employeeList = new ArrayList<Employee>() {{
  4. add(new Employee(1, 9, 10000, 10));
  5. add(new Employee(2, 9, 12000, 7));
  6. add(new Employee(3, 5, 10000, 12));
  7. add(new Employee(4, 5, 10000, 6));
  8. add(new Employee(5, 3, 5000, 3));
  9. add(new Employee(6, 1, 2500, 1));
  10. add(new Employee(7, 5, 8000, 10));
  11. add(new Employee(8, 3, 8000, 2));
  12. add(new Employee(9, 1, 3000, 5));
  13. add(new Employee(10, 1, 2500, 4));
  14. add(new Employee(11, 2, 2000, 4));
  15. }};
  16. Collections.sort(employeeList, comparator);
  17. System.out.println("ID\tLevel\tSalary\tYears");
  18. System.out.println("=============================");
  19. for (Employee employee : employeeList) {
  20. System.out.printf("%d\t%d\t%d\t%d\n", employee.getId(), employee.getLevel(), employee.getSalary(), employee.getYear());
  21. }
  22. System.out.println("=============================");
  23. }

整个完整代码如下所示:

  1. /**
  2. * 1、首先级别最高的排在前面,<br/>
  3. 2、如果级别相等,那么按工资排序,工资高的排在前面,<br/>
  4. 3、如果工资相当则按入职年数排序,入职时间最长的排在前面。<br/>
  5. *<p/>
  6. *created by OuyangPeng on 2016/8/2. <a href="http://blog.csdn.net/ouyang_peng">http://blog.csdn.net/ouyang_peng</a>
  7. */
  8. public class SortTest2 {
  9. /**
  10. * 雇员
  11. */
  12. class Employee {
  13. /**
  14. * ID
  15. */
  16. public int id;
  17. /**
  18. * 级别
  19. */
  20. public int level;
  21. /**
  22. * 工资
  23. */
  24. public int salary;
  25. /**
  26. * 入职年数
  27. */
  28. public int year;
  29. public int getId() {
  30. return id;
  31. }
  32. public void setId(int id) {
  33. this.id = id;
  34. }
  35. public int getLevel() {
  36. return level;
  37. }
  38. public void setLevel(int level) {
  39. this.level = level;
  40. }
  41. public int getSalary() {
  42. return salary;
  43. }
  44. public void setSalary(int salary) {
  45. this.salary = salary;
  46. }
  47. public int getYear() {
  48. return year;
  49. }
  50. public void setYear(int year) {
  51. this.year = year;
  52. }
  53. public Employee(int id, int level, int salary, int year) {
  54. this.id = id;
  55. this.level = level;
  56. this.salary = salary;
  57. this.year = year;
  58. }
  59. }
  60. private Comparator<Employee> comparator = new Comparator<Employee>() {
  61. @Override
  62. public int compare(Employee employee1, Employee employee2) {
  63. int cr = 0;
  64. //按级别降序排列
  65. int a = employee2.getLevel() - employee1.getLevel();
  66. if (a != 0) {
  67. cr = (a > 0) ? 3 : -1;
  68. } else {
  69. //按薪水降序排列
  70. a = employee2.getSalary() - employee1.getSalary();
  71. if (a != 0) {
  72. cr = (a > 0) ? 2 : -2;
  73. } else {
  74. //按入职年数降序排列
  75. a = employee2.getYear() - employee1.getYear();
  76. if (a != 0) {
  77. cr = (a > 0) ? 1 : -3;
  78. }
  79. }
  80. }
  81. return cr;
  82. }
  83. };
  84. @Test
  85. public void sortTest() throws Exception {
  86. List<Employee> employeeList = new ArrayList<Employee>() {{
  87. add(new Employee(1, 9, 10000, 10));
  88. add(new Employee(2, 9, 12000, 7));
  89. add(new Employee(3, 5, 10000, 12));
  90. add(new Employee(4, 5, 10000, 6));
  91. add(new Employee(5, 3, 5000, 3));
  92. add(new Employee(6, 1, 2500, 1));
  93. add(new Employee(7, 5, 8000, 10));
  94. add(new Employee(8, 3, 8000, 2));
  95. add(new Employee(9, 1, 3000, 5));
  96. add(new Employee(10, 1, 2500, 4));
  97. add(new Employee(11, 2, 2000, 4));
  98. }};
  99. Collections.sort(employeeList, comparator);
  100. System.out.println("ID\tLevel\tSalary\tYears");
  101. System.out.println("=============================");
  102. for (Employee employee : employeeList) {
  103. System.out.printf("%d\t%d\t%d\t%d\n", employee.getId(), employee.getLevel(), employee.getSalary(), employee.getYear());
  104. }
  105. System.out.println("=============================");
  106. }
  107. }

运行结果:

  1. ID Level Salary Years
  2. =============================
  3. 2 9 12000 7
  4. 1 9 10000 10
  5. 3 5 10000 12
  6. 4 5 10000 6
  7. 7 5 8000 10
  8. 8 3 8000 2
  9. 5 3 5000 3
  10. 11 2 2000 4
  11. 9 1 3000 5
  12. 10 1 2500 4
  13. 6 1 2500 1
  14. =============================

验证第一条件:首先按级别排序,级别最高的排在前面

从上面的运行结果可以发现,还是满足需求第一条要求的:首先按级别排序,级别最高的排在前面

1、首先从整体来看,是从级别最高的9级排序到级别最低的1级

  1. ID Level Salary Years
  2. =============================
  3. 2 9 12000 7
  4. 1 9 10000 10
  5. 3 5 10000 12
  6. 4 5 10000 6
  7. 7 5 8000 10
  8. 8 3 8000 2
  9. 5 3 5000 3
  10. 11 2 2000 4
  11. 9 1 3000 5
  12. 10 1 2500 4
  13. 6 1 2500 1
  14. =============================

验证第二条:如果级别相等,那么按工资排序,工资高的排在前面

2、当级别相同的情况下,如下两天记录:

  1. 2 9 12000 7
  2. 1 9 10000 10

则都是9级,这个时候是满足第二条要求的:如果级别相等,那么按工资排序,工资高的排在前面

下面的3条记录也是满足第二条要求的:

  1. 9 1 3000 5
  2. 10 1 2500 4
  3. 6 1 2500 1

则都是1级,工资为3000的排在工资为2500的前面。

验证第三条:如果工资相当则按入职年数排序,入职时间最长的排在前面

3、当级别和工资都相同的情况下,则比较入职年数。如下面的两条记录

  1. 10 1 2500 4
  2. 6 1 2500 1

级别都是1级,工资都是2500,年数为4的排在年数为1的前面。这个时候是满足第三条要求的:如果工资相当则按入职年数排序,入职时间最长的排在前面


其实Comparator接口直接写成下面的就行了

  1. private Comparator<Employee> comparator = new Comparator<Employee>() {
  2. @Override
  3. public int compare(Employee employee1, Employee employee2) {
  4. int cr = 0;
  5. //按级别降序排列
  6. int a = employee2.getLevel() - employee1.getLevel();
  7. if (a != 0) {
  8. cr = (a > 0) ? 1 : -1;
  9. } else {
  10. //按薪水降序排列
  11. a = employee2.getSalary() - employee1.getSalary();
  12. if (a != 0) {
  13. cr = (a > 0) ? 1 : -1;
  14. } else {
  15. //按入职年数降序排列
  16. a = employee2.getYear() - employee1.getYear();
  17. if (a != 0) {
  18. cr = (a > 0) ? 1 : -1;
  19. }
  20. }
  21. }
  22. return cr;
  23. }
  24. };

附录:java.util.Comparator接口源代码

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package java.util;
  18. /**
  19. * A {@code Comparator} is used to compare two objects to determine their ordering with
  20. * respect to each other. On a given {@code Collection}, a {@code Comparator} can be used to
  21. * obtain a sorted {@code Collection} which is <i>totally ordered</i>. For a {@code Comparator}
  22. * to be <i>consistent with equals</i>, its {code #compare(Object, Object)}
  23. * method has to return zero for each pair of elements (a,b) where a.equals(b)
  24. * holds true. It is recommended that a {@code Comparator} implements
  25. * {@link java.io.Serializable}.
  26. *
  27. * @since 1.2
  28. */
  29. public interface Comparator<T> {
  30. /**
  31. * Compares the two specified objects to determine their relative ordering. The ordering
  32. * implied by the return value of this method for all possible pairs of
  33. * {@code (lhs, rhs)} should form an <i>equivalence relation</i>.
  34. * This means that
  35. * <ul>
  36. * <li>{@code compare(a,a)} returns zero for all {@code a}</li>
  37. * <li>the sign of {@code compare(a,b)} must be the opposite of the sign of {@code
  38. * compare(b,a)} for all pairs of (a,b)</li>
  39. * <li>From {@code compare(a,b) > 0} and {@code compare(b,c) > 0} it must
  40. * follow {@code compare(a,c) > 0} for all possible combinations of {@code
  41. * (a,b,c)}</li>
  42. * </ul>
  43. *
  44. * @param lhs
  45. * an {@code Object}.
  46. * @param rhs
  47. * a second {@code Object} to compare with {@code lhs}.
  48. * @return an integer < 0 if {@code lhs} is less than {@code rhs}, 0 if they are
  49. * equal, and > 0 if {@code lhs} is greater than {@code rhs}.
  50. * @throws ClassCastException
  51. * if objects are not of the correct type.
  52. */
  53. public int compare(T lhs, T rhs);
  54. /**
  55. * Compares this {@code Comparator} with the specified {@code Object} and indicates whether they
  56. * are equal. In order to be equal, {@code object} must represent the same object
  57. * as this instance using a class-specific comparison.
  58. * <p>
  59. * A {@code Comparator} never needs to override this method, but may choose so for
  60. * performance reasons.
  61. *
  62. * @param object
  63. * the {@code Object} to compare with this comparator.
  64. * @return boolean {@code true} if specified {@code Object} is the same as this
  65. * {@code Object}, and {@code false} otherwise.
  66. * @see Object#hashCode
  67. * @see Object#equals
  68. */
  69. public boolean equals(Object object);
  70. }

作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!

转载请保留原文地址:http://blog.csdn.net/ouyang_peng

我的Java开发学习之旅------>Java利用Comparator接口对多个排序条件进行处理的更多相关文章

  1. 我的Java开发学习之旅------>Java 格式化类(java.util.Formatter)基本用法

    本文参考: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html http://www.blogjava.net/ ...

  2. 我的Java开发学习之旅------>Java使用Fork/Join框架来并行执行任务

    现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多. 虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并未这 ...

  3. 我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常

    今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常, ...

  4. 我的Java开发学习之旅------>Java使用ObjectOutputStream和ObjectInputStream序列号对象报java.io.EOFException异常的解决方法

    今天用ObjectOutputStream和ObjectInputStream进行对象序列化话操作的时候,报了java.io.EOFException异常. 异常代码如下: java.io.EOFEx ...

  5. Java之——利用Comparator接口对多个排序条件进行处理

    转载自:http://blog.csdn.net/l1028386804/article/details/56513205 膜拜大神··· 一.需求 假设现在有个如此的需求:需要对一个这样的雇员列表进 ...

  6. 我的Java开发学习之旅------>Java String对象作为参数传递的问题解惑

    又是一道面试题,来测试你的Java基础是否牢固. 题目:以下代码的运行结果是? public class TestValue { public static void test(String str) ...

  7. 我的Java开发学习之旅------>Java语言中方法的参数传递机制

    实参:如果声明方法时包含来了形参声明,则调用方法时必须给这些形参指定参数值,调用方法时传给形参的参数值也被称为实参. Java的实参值是如何传入方法?这是由Java方法的参数传递机制来控制的,Java ...

  8. 我的Java开发学习之旅------>Java经典排序算法之归并排序

    一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列 ...

  9. 我的Java开发学习之旅------>Java经典排序算法之快速排序

    一.算法思想     快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod).(1) 分治法的 ...

随机推荐

  1. 李洪强iOS开发OC[001]-NSLog函数的使用方法

  2. iOS开发多线程篇 04 —线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  3. windows server 2003下搭建amp环境

    参考: http://blog.csdn.net/binyao02123202/article/details/7578914 http://4359260.blog.51cto.com/434926 ...

  4. DMA—直接存储区访问

    本章参考资料:< STM32F4xx 中文参考手册> DMA 控制器章节.学习本章时,配合< STM32F4xx 中文参考手册> DMA 控制器章节一起阅读,效果会更佳,特别是 ...

  5. 通用采集器Modbus协议应用

    1.  功能码 通用采集器一般包含DI,DO,AI相关接口,对此类接口主要应用功能码01~06. 3类接口具体对应关系如下: 继电器定义,功能码01/05(01:读线圈,05写线圈) 序号       ...

  6. 如何Vue-cli开始使用在Vue.js项目中启动TDD(测试驱动开发)

    通常,使用测试驱动开发(TDD)最困难的部分是开始.你必须下载带有奇怪依赖项的软件包,让测试套件与你的构建系统协同工作,然后你必须弄清楚如何编写一个测试!难怪这么多的开发者在你提起它的时候就开始跑开了 ...

  7. 在windows下安装Redis步骤(收集)

    一.下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的windows版本的,现在官网以及没有下载地址,只能在github上下载,官网只提供linux版本的下载 官网下载地址 ...

  8. text样式

    text-stroke(文本描边)和text-fill-color(文本填充色)注意点: 目前这两个属性只有webkit内核的Safari和Chrome支持,例如: -webkit-text-stro ...

  9. JS 怎么刷新当前页面

    reload 方法,该方法强迫浏览器刷新当前页面. 语法:location.reload([bForceGet]) 参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取当前页 ...

  10. mac上制作u盘启动盘

    Mac上制作Ubuntu USB启动盘 一.下载ubuntu iso镜像 二.将iso转换为img文件 $ hdiutil convert -format UDRW -o /path/to/gener ...