我的Java开发学习之旅------>Java利用Comparator接口对多个排序条件进行处理
一、需求
假设现在有个如此的需求:需要对一个这样的雇员列表进行排序,排序规则如下:
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接口对多个排序条件进行处理的更多相关文章
- 我的Java开发学习之旅------>Java 格式化类(java.util.Formatter)基本用法
本文参考: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html http://www.blogjava.net/ ...
- 我的Java开发学习之旅------>Java使用Fork/Join框架来并行执行任务
现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多. 虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并未这 ...
- 我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常
今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常, ...
- 我的Java开发学习之旅------>Java使用ObjectOutputStream和ObjectInputStream序列号对象报java.io.EOFException异常的解决方法
今天用ObjectOutputStream和ObjectInputStream进行对象序列化话操作的时候,报了java.io.EOFException异常. 异常代码如下: java.io.EOFEx ...
- Java之——利用Comparator接口对多个排序条件进行处理
转载自:http://blog.csdn.net/l1028386804/article/details/56513205 膜拜大神··· 一.需求 假设现在有个如此的需求:需要对一个这样的雇员列表进 ...
- 我的Java开发学习之旅------>Java String对象作为参数传递的问题解惑
又是一道面试题,来测试你的Java基础是否牢固. 题目:以下代码的运行结果是? public class TestValue { public static void test(String str) ...
- 我的Java开发学习之旅------>Java语言中方法的参数传递机制
实参:如果声明方法时包含来了形参声明,则调用方法时必须给这些形参指定参数值,调用方法时传给形参的参数值也被称为实参. Java的实参值是如何传入方法?这是由Java方法的参数传递机制来控制的,Java ...
- 我的Java开发学习之旅------>Java经典排序算法之归并排序
一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列 ...
- 我的Java开发学习之旅------>Java经典排序算法之快速排序
一.算法思想 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod).(1) 分治法的 ...
随机推荐
- python学习之with...as语句
python中的with...as...语句类似于try...finally...语句: # -*- coding: utf-8 -*- # """ with...as. ...
- 去掉IntelliJ IDEA代码编辑区域的竖线
(网络配图) 作为从事编程或者测试工作的人来说,尤其是有强迫症的,看着非常痛苦,我们来看看怎么去掉 在 Settings-> Editor-> General-> Appearanc ...
- vue 插件
开发插件 插件通常会为vue添加全局功能,插件的范围没有限制--一般有下面几种: 1,添加全局方法或者属性,例:vue-coustom-element 2,添加全局资源:指令.过滤器,.过渡等,如vu ...
- android6.0 adbd深入分析(二)adb驱动数据的处理、写数据到adb驱动节点
上篇博客最后讲到在output_thread中.读取了adb驱动的数据后.就调用write_packet(t->fd, t->serial, &p)函数,把数据网socket ...
- SIGBUS 和 SIGSEGV
一.导致SIGSEGV 1.试图对仅仅读映射区域进行写操作 . 2.訪问的内存已经被释放,也就是已经不存在或者越界. 3.官方说法是: SIGSEGV --- Segment Fault. ...
- hbase练习题
-- 配置环境变量,因为在hbase中有的地方可能用到了环境变量-- bin/start-hbase.sh-- bin/hbase shell-- 访问http://mini0:16010/ 可以看浏 ...
- Jquery Deferred 详解
近期由于公司项目主要由我来负责前端,所以打算优化一下代码.在jquery 里面有个Deferred的对象.为了研究这个也看了不少资料,其中阮一峰的博客写的很详细,这里转载一下. 一.什么是deferr ...
- 【iOS越狱开发】如何将应用打包成.ipa文件
在项目开发中,我们常常需要将工程文件打包成.ipa文件,提供给越狱的iphone安装. 下面是一种方法: 1.首先应该给工程安装好配置文件(这里不再敖述),在ios device的状态下,运行成功. ...
- UVA 12034 Race (递推神马的)
Disky and Sooma, two of the biggest mega minds of Bangladesh went to a far country. They ate, coded ...
- css3 图片 悬停效果
纯css实现 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> ...