zoukankan      html  css  js  c++  java
  • Java:集合,对列表(List)中的自定义对象按属性(字段)排序(正序、倒序)的方法

    1. 要求

    对列表(List)中的自定义对象,要求能够按照对象的属性(字段)进行排序(正序、倒序)。

    如:用户对象(Member)有用户名(username)、级别(level)、出生日期(birthday)等字段,要求可以分别对它的三个字段进行排序。

    2. 实现思路

    1. 对于自定义对象,可以在自定义对象中实现Comparable接口,然后再调用Collections.sort的方法实现排序,只能是针对一个属性(字段),维持一个顺序;要实多字段任意选择一个排序,同样需要通过调用Collections.sort(List<T> list, Comparator<? super T> c)方法,传进一个Comparator来实现。

    2. 为避免上述步骤中复杂且重复的代码,可以写一个通用的排序类,能够对自定义对象,针对不同的属性(字段),实现排序(正序、倒序)。

    3. 实现代码

    Member类

    package com.clzhang.sample.collections;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * 测试用实体类
     * @author acer
     *
     */
    public class Member implements Comparable<Member>{
        // 格式化日期用
        private static final SimpleDateFormat MY_SDF = new SimpleDateFormat(
                "yyyy-MM-dd");
        
        // 几个属性
        private int id;
        private String username;
        private int level;
        private Date birthday;
        
        // 构造函数
        public Member(int id, String username, int level, String birthday) throws Exception {
            this.id = id;
            this.username = username;
            this.level = level;
            this.birthday = new Date(MY_SDF.parse(birthday).getTime());
        }
        
        // Getters
        public String getUsername() {
            return username;
        }
    
        public int getLevel() {
            return level;
        }
    
        public Date getBirthday() {
            return birthday;
        }
        
        // 返回打印用
        @Override
        public String toString() {
            return id + "|" + username + "|" + level + "|" + MY_SDF.format(birthday);
        }
        
        // 注意:如果使用MySortList类,则此方法不再需要。因为此方法是提供给Collections.sort方法使用的。
        @Override
        public int compareTo(Member m) {
            // 只能对一个字段做比较,如果做整个对象的比较就实现不了按指定字段排序了。
            return this.getUsername().compareTo(m.getUsername());
        }
    }

    MySortList类

    package com.clzhang.sample.collections;
    
    import java.util.*;
    import java.lang.reflect.Method;
    import java.lang.reflect.InvocationTargetException;
    
    /**
     * 这是一个自定义排序的类,专门针对列表(List)中的数据进行排序;可按指定方法进行。
     * 目前实现对字符串(String)、日期(Date)、整型(Integer)等三种对象进行排序。
     * @author acer
     *
     * @param <E>
     */
    public class MySortList<E> {
        
        /**
         * 对列表中的数据按指定字段进行排序。要求类必须有相关的方法返回字符串、整型、日期等值以进行比较。
         * @param list
         * @param method
         * @param reverseFlag
         */
        public void sortByMethod(List<E> list, final String method,
                final boolean reverseFlag) {
            Collections.sort(list, new Comparator<Object>() {
                @SuppressWarnings("unchecked")
                public int compare(Object arg1, Object arg2) {
                    int result = 0;
                    try {
                        Method m1 = ((E) arg1).getClass().getMethod(method, null);
                        Method m2 = ((E) arg2).getClass().getMethod(method, null);
                        Object obj1 = m1.invoke(((E)arg1), null);
                        Object obj2 = m2.invoke(((E)arg2), null);
                        if(obj1 instanceof String) {
                            // 字符串
                            result = obj1.toString().compareTo(obj2.toString());
                        }else if(obj1 instanceof Date) {
                            // 日期
                            long l = ((Date)obj1).getTime() - ((Date)obj2).getTime();
                            if(l > 0) {
                                result = 1;
                            }else if(l < 0) {
                                result = -1;
                            }else {
                                result = 0;
                            }
                        }else if(obj1 instanceof Integer) {
                            // 整型(Method的返回参数可以是int的,因为JDK1.5之后,Integer与int可以自动转换了)
                            result = (Integer)obj1 - (Integer)obj2;
                        }else {
                            // 目前尚不支持的对象,直接转换为String,然后比较,后果未知
                            result = obj1.toString().compareTo(obj2.toString());
                            
                            System.err.println("MySortList.sortByMethod方法接受到不可识别的对象类型,转换为字符串后比较返回...");
                        }
                        
                        if (reverseFlag) {
                            // 倒序
                            result = -result;
                        }
                    } catch (NoSuchMethodException nsme) {
                        nsme.printStackTrace();
                    } catch (IllegalAccessException iae) {
                        iae.printStackTrace();
                    } catch (InvocationTargetException ite) {
                        ite.printStackTrace();
                    }
    
                    return result;
                }
            });
        }
    
        // 测试函数
        public static void main(String[] args) throws Exception {
            // 生成自定义对象,然后对它按照指定字段排序
            List<Member> listMember = new ArrayList<Member>();
            listMember.add(new Member(1, "wm123", 3, "1992-12-01"));
            listMember.add(new Member(2, "a234", 8, "1995-12-01"));
            listMember.add(new Member(3, "m456", 12, "1990-12-01"));
            System.out.println("Member当前顺序...");
            System.out.println(listMember);
            
            // 方式一排序输出
            System.out.println("Member默认排序(用自带的compareTo方法)后...");
            Collections.sort(listMember);
            System.out.println(listMember);
            System.out.println("Member倒序(用自带的compareTo方法)后...");
            Collections.sort(listMember, Collections.reverseOrder());
            System.out.println(listMember);
            
            // 方式二排序输出
            MySortList<Member> msList = new MySortList<Member>();
            msList.sortByMethod(listMember, "getUsername", false);
            System.out.println("Member按字段用户名排序后...");
            System.out.println(listMember);
    
            msList.sortByMethod(listMember, "getLevel", false);
            System.out.println("Member按字段级别排序后...");
            System.out.println(listMember);
    
            msList.sortByMethod(listMember, "getBirthday", true);
            System.out.println("Member按字段出生日期倒序后...");
            System.out.println(listMember);
        }
    }

    输出:

    Member当前顺序...
    [1|wm123|3|1992-12-01, 2|a234|8|1995-12-01, 3|m456|12|1990-12-01]
    Member默认排序(用自带的compareTo方法)后...
    [2|a234|8|1995-12-01, 3|m456|12|1990-12-01, 1|wm123|3|1992-12-01]
    Member倒序(用自带的compareTo方法)后...
    [1|wm123|3|1992-12-01, 3|m456|12|1990-12-01, 2|a234|8|1995-12-01]
    Member按字段用户名排序后...
    [2|a234|8|1995-12-01, 3|m456|12|1990-12-01, 1|wm123|3|1992-12-01]
    Member按字段级别排序后...
    [1|wm123|3|1992-12-01, 2|a234|8|1995-12-01, 3|m456|12|1990-12-01]
    Member按字段出生日期倒序后...
    [2|a234|8|1995-12-01, 1|wm123|3|1992-12-01, 3|m456|12|1990-12-01]

  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/nayitian/p/3322267.html
Copyright © 2011-2022 走看看