一、需求

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

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

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

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

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

     /**
* 雇员
*/
class Employee {
/**
* ID
*/
public int id;
/**
* 级别
*/
public int level;
/**
* 工资
*/
public int salary;
/**
* 入职年数
*/
public int year; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public int getLevel() {
return level;
} public void setLevel(int level) {
this.level = level;
} public int getSalary() {
return salary;
} public void setSalary(int salary) {
this.salary = salary;
} public int getYear() {
return year;
} public void setYear(int year) {
this.year = year;
} public Employee(int id, int level, int salary, int year) {
this.id = id;
this.level = level;
this.salary = salary;
this.year = year;
}
}

二、实现Comparator接口

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

private Comparator<Employee> comparator = new Comparator<Employee>() {
@Override
public int compare(Employee employee1, Employee employee2) {
int cr = 0;
//按级别降序排列
int a = employee2.getLevel() - employee1.getLevel();
if (a != 0) {
cr = (a > 0) ? 3 : -1;
} else {
//按薪水降序排列
a = employee2.getSalary() - employee1.getSalary();
if (a != 0) {
cr = (a > 0) ? 2 : -2;
} else {
//按入职年数降序排列
a = employee2.getYear() - employee1.getYear();
if (a != 0) {
cr = (a > 0) ? 1 : -3;
}
}
}
return cr;
}
};

三、验证排序结果

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

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

整个完整代码如下所示:

/**
* 1、首先级别最高的排在前面,<br/>
2、如果级别相等,那么按工资排序,工资高的排在前面,<br/>
3、如果工资相当则按入职年数排序,入职时间最长的排在前面。<br/>
*<p/>
*created by OuyangPeng on 2016/8/2. <a href="http://blog.csdn.net/ouyang_peng">http://blog.csdn.net/ouyang_peng</a>
*/
public class SortTest2 {
/**
* 雇员
*/
class Employee {
/**
* ID
*/
public int id;
/**
* 级别
*/
public int level;
/**
* 工资
*/
public int salary;
/**
* 入职年数
*/
public int year; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public int getLevel() {
return level;
} public void setLevel(int level) {
this.level = level;
} public int getSalary() {
return salary;
} public void setSalary(int salary) {
this.salary = salary;
} public int getYear() {
return year;
} public void setYear(int year) {
this.year = year;
} public Employee(int id, int level, int salary, int year) {
this.id = id;
this.level = level;
this.salary = salary;
this.year = year;
}
} private Comparator<Employee> comparator = new Comparator<Employee>() {
@Override
public int compare(Employee employee1, Employee employee2) {
int cr = 0;
//按级别降序排列
int a = employee2.getLevel() - employee1.getLevel();
if (a != 0) {
cr = (a > 0) ? 3 : -1;
} else {
//按薪水降序排列
a = employee2.getSalary() - employee1.getSalary();
if (a != 0) {
cr = (a > 0) ? 2 : -2;
} else {
//按入职年数降序排列
a = employee2.getYear() - employee1.getYear();
if (a != 0) {
cr = (a > 0) ? 1 : -3;
}
}
}
return cr;
}
}; @Test
public void sortTest() throws Exception {
List<Employee> employeeList = new ArrayList<Employee>() {{
add(new Employee(1, 9, 10000, 10));
add(new Employee(2, 9, 12000, 7));
add(new Employee(3, 5, 10000, 12));
add(new Employee(4, 5, 10000, 6));
add(new Employee(5, 3, 5000, 3));
add(new Employee(6, 1, 2500, 1));
add(new Employee(7, 5, 8000, 10));
add(new Employee(8, 3, 8000, 2));
add(new Employee(9, 1, 3000, 5));
add(new Employee(10, 1, 2500, 4));
add(new Employee(11, 2, 2000, 4));
}};
Collections.sort(employeeList, comparator);
System.out.println("ID\tLevel\tSalary\tYears");
System.out.println("=============================");
for (Employee employee : employeeList) {
System.out.printf("%d\t%d\t%d\t%d\n", employee.getId(), employee.getLevel(), employee.getSalary(), employee.getYear());
}
System.out.println("=============================");
}
}

运行结果:

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

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

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

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

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

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

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

2   9   12000   7
1 9 10000 10

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

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

9   1   3000    5
10 1 2500 4
6 1 2500 1

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

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

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

10  1   2500    4
6 1 2500 1

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


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

private Comparator<Employee> comparator = new Comparator<Employee>() {
@Override
public int compare(Employee employee1, Employee employee2) {
int cr = 0;
//按级别降序排列
int a = employee2.getLevel() - employee1.getLevel();
if (a != 0) {
cr = (a > 0) ? 1 : -1;
} else {
//按薪水降序排列
a = employee2.getSalary() - employee1.getSalary();
if (a != 0) {
cr = (a > 0) ? 1 : -1;
} else {
//按入职年数降序排列
a = employee2.getYear() - employee1.getYear();
if (a != 0) {
cr = (a > 0) ? 1 : -1;
}
}
}
return cr;
}
};

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

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package java.util; /**
* A {@code Comparator} is used to compare two objects to determine their ordering with
* respect to each other. On a given {@code Collection}, a {@code Comparator} can be used to
* obtain a sorted {@code Collection} which is <i>totally ordered</i>. For a {@code Comparator}
* to be <i>consistent with equals</i>, its {code #compare(Object, Object)}
* method has to return zero for each pair of elements (a,b) where a.equals(b)
* holds true. It is recommended that a {@code Comparator} implements
* {@link java.io.Serializable}.
*
* @since 1.2
*/
public interface Comparator<T> {
/**
* Compares the two specified objects to determine their relative ordering. The ordering
* implied by the return value of this method for all possible pairs of
* {@code (lhs, rhs)} should form an <i>equivalence relation</i>.
* This means that
* <ul>
* <li>{@code compare(a,a)} returns zero for all {@code a}</li>
* <li>the sign of {@code compare(a,b)} must be the opposite of the sign of {@code
* compare(b,a)} for all pairs of (a,b)</li>
* <li>From {@code compare(a,b) > 0} and {@code compare(b,c) > 0} it must
* follow {@code compare(a,c) > 0} for all possible combinations of {@code
* (a,b,c)}</li>
* </ul>
*
* @param lhs
* an {@code Object}.
* @param rhs
* a second {@code Object} to compare with {@code lhs}.
* @return an integer < 0 if {@code lhs} is less than {@code rhs}, 0 if they are
* equal, and > 0 if {@code lhs} is greater than {@code rhs}.
* @throws ClassCastException
* if objects are not of the correct type.
*/
public int compare(T lhs, T rhs); /**
* Compares this {@code Comparator} with the specified {@code Object} and indicates whether they
* are equal. In order to be equal, {@code object} must represent the same object
* as this instance using a class-specific comparison.
* <p>
* A {@code Comparator} never needs to override this method, but may choose so for
* performance reasons.
*
* @param object
* the {@code Object} to compare with this comparator.
* @return boolean {@code true} if specified {@code Object} is the same as this
* {@code Object}, and {@code false} otherwise.
* @see Object#hashCode
* @see Object#equals
*/
public boolean equals(Object object);
}

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

转载请保留原文地址: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. javascript构造函数的理解

    构造函数是在javascript文档的创建对象当中提到的,主要目的是为了解决代码复用,能够大量产生同类型而多作用的方法 在javascript中给出了几种创建对象的模式: 1.对象字面量 例: var ...

  2. maven仓库国内镜像

    <mirror>        <id>alimaven</id>        <name>aliyun maven</name>     ...

  3. c# 获取Excel内容的分析

    现在主流的Excel文档有2003和2007 c#获取 Excel2003 连接字符串 string strConn = "Provider=Microsoft.Jet.OLEDB.4.0; ...

  4. JVM Specification 9th Edition (4) Chapter 3. Compiling for the Java Virtual Machine

    Chapter 3. Compiling for the Java Virtual Machine 内容列表 3.1. Format of Examples 3.2. Use of Constants ...

  5. linux2.6内核netfilter架构分析

    1.2.6内核的netfilter与2.4的有很大不同: ChangeLog-2.6.15 中有下面这样的描述: commit 9fb9cbb1082d6b31fb45aa1a14432449a0df ...

  6. 一个IDEA和jackson结合的一个错误异常

    一个字段是isSend,用IDEA自动生成的getter/setter方法名会把is去掉.变成getSend()/setSend(). 当返回的时候使用Jackson转json的时候,就会把isSen ...

  7. JS 怎么刷新当前页面

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

  8. Struts2包含哪些标签?

    Struts2包含哪些标签? 解答: A: <s:a href=”"></s:a>—–超链接,类似于html里的<a></a> <s:a ...

  9. linux下的线程池

    什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比任 ...

  10. Attribute在.net编程中的应用(一)

    Attribute的基本概念 经常有朋友问,Attribute是什么?它有什么用?好像没有这个东东程序也能运行.实际上在.Net中,Attribute是一个非常重要的组成部分,为了帮助大家理解和掌握A ...