在项目开发中,经常会遇到一些排序的问题。
现在有一个操作VO(Member),它有三个属性,分别为:id(String)、name(String)和age(int)。
情景一:
初始页面,Member对象会以id排序,现在name中保存的是英文名,需对name进行排序;
首先我们来看我们要用到的Java API中的一个接口Comparator
比较函数强行对某些对象 collection 进行整体排序。可以将 Comparator 传递给 sort 方法(如 Collections.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如 TreeSet 或 TreeMap)的顺序。
当且仅当对于一组元素 S 中的每个 e1 和 e2 而言,(compare((Object)e1, (Object)e2)==0) 与 e1.equals((Object)e2) 具有相等的布尔值时,Comparator c 强行对 S 进行的排序才叫做与等号一致 的排序。
也就是说,只要我们新建一个类用于排序,实现Comparator接口的compare()就可以了;
Member memberOp1 = (Member) op1;
Member memberOp2 = (Member) op2;
// 按姓名(英文)排序
return memberOp1.getName().compareTo(memberOp2.getName());
}
然后在使用时通过调用Collections.sort()就可以了;
具体步骤如下:
1、新建一个工程Object排序,然后建三个包,一个为:com.coderdream.util,用于存放“比较工具类”;另一个为:com.coderdream.view,用于存放操作VO,另一个包名为:com.coderdream.service,存放操作VO的类,这里我写两个测试类,分别用于测试中英文。
代码1:
* Member.java
*
* Provider: CoderDream's Studio
*
* History
* Date(DD/MM/YYYY) Author Description
* ----------------------------------------------------------------------------
* 2007/12/19 CoderDream Created
*/
package com.coderdream.view;
/**
* discription: 操作對象VO
*
* @author CoderDream
*
*/
public class Member {
/**
* ID
*/
private String id;
/**
* 名字
*/
private String name;
/**
* 年齡
*/
private int age;
/**
* @param name
* @param age
*/
public Member(String id, String name, int age) {
this .id = id;
this .name = name;
this .age = age;
}
/**
* @return
*/
public String getName() {
return name;
}
/**
* @param name
*/
public void setName(String name) {
this .name = name;
}
/**
* @return
*/
public int getAge() {
return age;
}
/**
* @param age
*/
public void setAge( int age) {
this .age = age;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(String id) {
this .id = id;
}
}
代码2:
* CompareName.java
*
* Provider: CoderDream's Studio
*
* History
* Date(DD/MM/YYYY) Author Description
* ----------------------------------------------------------------------------
* 2007/12/19 CoderDream Created
*/
package com.coderdream.util;
import java.util.Comparator;
import com.coderdream.view.Member;
/**
* discription:根據英文字母比較
*
* @author CoderDream
*
*/
public class CompareName implements Comparator {
public int compare(Object op1, Object op2) {
Member memberOp1 = (Member) op1;
Member memberOp2 = (Member) op2;
// 按姓名(英文)排序
return memberOp1.getName().compareTo(memberOp2.getName());
}
}
代码3:
* CompareAge.java
*
* Provider: CoderDream's Studio
*
* History
* Date(DD/MM/YYYY) Author Description
* ----------------------------------------------------------------------------
* 2007/12/19 CoderDream Created
*/
package com.coderdream.util;
import java.util.Comparator;
import com.coderdream.view.Member;
/**
* discription: 根據年齡比較,由小到大
*
* @author CoderDream
*
*/
public class CompareAge implements Comparator {
public int compare(Object op1, Object op2) {
Member memberOp1 = (Member) op1;
Member memberOp2 = (Member) op2;
// 按 年齡 排序
return memberOp1.getAge() < memberOp2.getAge() ? 0 : 1 ;
}
}
代码4:
* Client1.java
*
* Provider: CoderDream's Studio
*
* History
* Date(DD/MM/YYYY) Author Description
* ----------------------------------------------------------------------------
* 2007/12/19 CoderDream Created
*/
package com.coderdream.service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.coderdream.util.CompareAge;
import com.coderdream.util.CompareName;
import com.coderdream.view.Member;
/**
* discription:測試類1,按字母和年齡比較
*
* @author CoderDream
*
*/
public class Client1 {
/**
* @param args
*/
public static void main(String[] args) {
// 新建链表并加入元素
List < Member > members = new ArrayList < Member > ();
members.add( new Member( " 01 " , " Andy " , 20 ));
members.add( new Member( " 02 " , " Dell " , 26 ));
members.add( new Member( " 03 " , " Felex " , 24 ));
members.add( new Member( " 04 " , " Bill " , 21 ));
members.add( new Member( " 05 " , " Cindy " , 28 ));
// 输出排序后的链表
System.out.println( " Original Data: " );
for (Member member : members) {
System.out.println( " " + member.getName() + " : " + member.getAge());
}
// 按名字排序
Collections.sort(members, new CompareName());
System.out.println( " Sort by Name: " );
// 输出排序后的链表
for (Member member : members) {
System.out.println( " " + member.getName() + " : " + member.getAge());
}
// 按 年齡 排序
Collections.sort(members, new CompareAge());
System.out.println( " Sort by Age: " );
// 输出排序后的链表
for (Member member : members) {
System.out.println( " " + member.getName() + " : " + member.getAge());
}
}
}
运行结果:
Andy: 20
Dell: 26
Felex: 24
Bill: 21
Cindy: 28
Sort by Name:
Andy: 20
Bill: 21
Cindy: 28
Dell: 26
Felex: 24
Sort by Age:
Andy: 20
Bill: 21
Felex: 24
Dell: 26
Cindy: 28
情景二:
初始页面,Member对象会以id排序,现在name中保存的是中文名(字符集为GBK,包括简体中文和繁体中文),需对name进行排序;
这里我们要用到SourceForge的pinyin4j项目的jar包,可以解决这个问题,pinyin4j的项目地址是: http://pinyin4j.sourceforge.net/ ,本文最后的源代码中已包含此Jar包。
注意,由于这里要比较的是对象,所以我们实现接口:Comparator<Object>
这里我们会用到包中PinyinHelper类的toHanyuPinyinStringArray(char c)方法,该方法返回该字的汉语拼音数组:
String[] a = PinyinHelper.toHanyuPinyinStringArray(c);
代码5:
* CompareNamePinyin.java
*
* Provider: CoderDream's Studio
*
* History
* Date(DD/MM/YYYY) Author Description
* ----------------------------------------------------------------------------
* 2007/12/19 CoderDream Created
*/
package com.coderdream.util;
import java.util.Comparator;
import net.sourceforge.pinyin4j.PinyinHelper;
import com.coderdream.view.Member;
/**
* discription:根據漢語拼音比較,第一個字相同再比較第二個字
*
* @author CoderDream
*
*/
public class CompareNamePinyin implements Comparator < Object > {
public int compare(Object obj1, Object obj2) {
Member m1 = (Member)obj1;
Member m2 = (Member)obj2;
String o1 = m1.getName();
String o2 = m2.getName();
for ( int i = 0 ; i < o1.length() && i < o2.length(); i ++ ) {
char c1 = o1.charAt(i);
char c2 = o2.charAt(i);
String pinyin1 = pinyin(c1);
String pinyin2 = pinyin(c2);
if (pinyin1 != null && pinyin2 != null ) {
if ( ! pinyin1.equals(pinyin2)) {
return pinyin1.compareTo(pinyin2);
}
} else {
if (c1 != c2) {
return c1 - c2;
}
}
}
return o1.length() - o2.length();
}
/**
* 字符的拼音,多音字就得到第一个拼音。不是汉字,就return null。
*
* @param c
* @return
*/
private String pinyin( char c) {
// 返回该字的汉语拼音数字,如“王”字返回:[wang2, wang4]
// 说明该字有两种读法,分别为wang2,第二声,wang4,第四声
String[] a = PinyinHelper.toHanyuPinyinStringArray(c);
if (a == null ){
return null ;
}
return a[ 0 ];
}
}
* Client2.java
*
* Provider: CoderDream's Studio
*
* History
* Date(DD/MM/YYYY) Author Description
* ----------------------------------------------------------------------------
* 2007/12/19 CoderDream Created
*/
package com.coderdream.service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.coderdream.util.CompareAge;
import com.coderdream.util.CompareNamePinyin;
import com.coderdream.view.Member;
/**
* discription: 測試類2,按字母和年齡比較
*
* @author CoderDream
*
*/
public class Client2 {
/**
* @param args
*/
public static void main(String[] args) {
// 新建链表并加入元素
List < Member > members = new ArrayList < Member > ();
members.add( new Member( " 01 " , " 王五 " , 20 ));
members.add( new Member( " 02 " , " 劉六 " , 26 ));
members.add( new Member( " 03 " , " 錢一 " , 24 ));
members.add( new Member( " 04 " , " 趙二 " , 21 ));
members.add( new Member( " 05 " , " 李四 " , 29 ));
members.add( new Member( " 06 " , " 張三 " , 28 ));
members.add( new Member( " 07 " , " 張七 " , 25 ));
// 输出排序后的链表
System.out.println( " Original Data: " );
for (Member member : members) {
System.out.println( " " + member.getName() + " : " + member.getAge());
}
// 按名字排序
Collections.sort(members, new CompareNamePinyin());
System.out.println( " Sort by Name: " );
// 输出排序后的链表
for (Member member : members) {
System.out.println( " " + member.getName() + " : " + member.getAge());
}
// 按 年齡 排序
Collections.sort(members, new CompareAge());
System.out.println( " Sort by Age: " );
// 输出排序后的链表
for (Member member : members) {
System.out.println( " " + member.getName() + " : " + member.getAge());
}
}
}
王五: 20
劉六: 26
錢一: 24
趙二: 21
李四: 29
張三: 28
張七: 25
Sort by Name:
李四: 29
劉六: 26
錢一: 24
王五: 20
張七: 25
張三: 28
趙二: 21
Sort by Age:
王五: 20
趙二: 21
錢一: 24
張七: 25
劉六: 26
張三: 28
李四: 29
源代码(包含Jar包),可直接由eclipse导入
参考:
1、 中文排序 - 汉语拼音
2、 用匿名类实现Comparator实现链表排序的例子