从制造到创造
软件工程师成长之路
posts - 292,  comments - 96,  trackbacks - 0

在项目开发中,经常会遇到一些排序的问题。
现在有一个操作VO(Member),它有三个属性,分别为:id(String)、name(String)和age(int)。

情景一:


    初始页面,Member对象会以id排序,现在name中保存的是英文名,需对name进行排序;

首先我们来看我们要用到的Java API中的一个接口Comparator

public interface Comparator<T>

比较函数强行对某些对象 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()就可以了;

    public int compare(Object op1, Object op2) {
        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());
        }
    }

}

运行结果:

Original Data: 
  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)方法,该方法返回该字的汉语拼音数组:

        //返回该字的汉语拼音数组,如“王”字返回:[wang2, wang4],说明该字有两种读法,分别为wang2,第二声,wang4,第四声
        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];
    }

}
代码6:
/*
 * 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());
        }
    }

}
输出结果:
Original Data: 
  王五:
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实现链表排序的例子
posted on 2007-12-19 16:07 CoderDream 阅读(1691) 评论(0)  编辑  收藏 所属分类: 经验点滴

只有注册用户登录后才能发表评论。


网站导航:
 

<2007年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

常用链接

留言簿(9)

我参与的团队

随笔分类(245)

随笔档案(239)

文章分类(3)

文章档案(3)

收藏夹(576)

友情链接

搜索

  •  

积分与排名

  • 积分 - 456249
  • 排名 - 114

最新评论

阅读排行榜

评论排行榜