Java之自定义排序工具类

"Java的封装,你到底了解了吗? 一个工具类,便知你的水平~ "

  1. 引入

在项目开发中,经常会遇到需要对一个复杂对象的集合进行规则排序,可能需要根据某一字段排序,也可能需要根据某些字段排序,导致冗余的代码看起来既复杂又繁琐。因此,我们可以通过封装一个通用的工具类,来针对所有的复杂对象进行抽象处理。 这样会使你的代码显得更加具备通用性,并且可适配。

  1. 理解

首先,在Java当中,我们可能会想到一个常用的工具类,那就是Collections。
Collections类提供了对集合元素进行排序、反转方法。

●void sort(List) 
该方法用于对List内的元素排序。

● void shuffle(List)
该方法用于对List内的元素进行随机排序。

● void reverse(List)
该方法用于对List内的元素进行逆序排序。

创建一个Person实体类
	

    public class Person {
    	    private String userName;
    	    private String password;
    	    private Integer age;
    	    //setter、getter
    }
  传统的实现,我们会这样操作:

	 main() {
        List<Person> personList = new ArrayList<>();
        Person person1 = new Person("aaa","123456",25);
        Person person2 = new Person("bbb","123456",15);
        Person person3 = new Person("ccc","123456",20);

        personList.add(person1);
        personList.add(person2);
        personList.add(person3);
        //排序前
        if (personList != null && personList.size() > 0) {
            for (Person person : personList) {
                System.out.println(person);
            }
            System.out.println("-------------");
        }
        //排序
        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                //return p1.getAge() - p2.getAge(); //表示升序
                return p2.getAge() - p1.getAge();   //表示降序
            }
        });
        //排序后
        if (personList != null && personList.size() > 0) {
            for (Person person : personList) {
                System.out.println(person);
            }
        }
    }
输出结果:

	排序前:
	Person{userName='aaa', password='123456', age=25}
	Person{userName='bbb', password='123456', age=15}
	Person{userName='ccc', password='123456', age=20}
	               
	排序后:
	Person{userName='aaa', password='123456', age=25}
	Person{userName='ccc', password='123456', age=20}
	Person{userName='bbb', password='123456', age=15}
  • sort方法默认的是正序,也可以倒序排列。

  • 此种方式相对灵活,并且不需要实体类实现Comparable接口

  • 而且无论list中的类型是实体类还是Map,都可以适用。

    如果想使用sort中带一个参数的排序,则该实体类必须实现Comparable,并且重写compareTo方法,否则就会报异常
    The method sort(List) in the type Collections is not applicable for the arguments (List)
    意思是参数类型为List时,sort方法无法执行,原因是泛型没有继承Comparable接口。

  • 改造:

     public class Person implements Comparable<Person> {
         private String userName;
         private String password;
         private Integer age;
     
         @Override
         public int compareTo(Person person) {
         //按照年龄正序
         //return this.getAge().compareTo(person.getAge());
         //按照年龄进行排序 (并且是倒序)
             return person.getAge().compareTo(this.getAge());
         }
     }
    

    测试结果:

     排序前:
     Person{userName='aaa', password='123456', age=25}
     Person{userName='bbb', password='123456', age=15}
     Person{userName='ccc', password='123456', age=20}
                    
     排序后:
     Person{userName='aaa', password='123456', age=25}
     Person{userName='ccc', password='123456', age=20}
     Person{userName='bbb', password='123456', age=15}
    
  1. 编写工具类
    而以上的代码,在较大的项目中使用,尽管可以一一实现,但只针对具体的单一实现类,以及指定的属性配置,才可实现你所需要的排序方式,不足以达到通用的效果。那现在,我们就来写一个通用的实现类,来达到此目的。

     public class CollectionsUtil {
    
         public static final String DESC = "desc";
         public static final String ASC = "asc";
     
         /**
          * 对list中的元素按升序排列.
          * 
          * @param list 排序集合
          * @param field 排序字段
          * @return
          */
         public static List<?> sort(List<?> list, final String field) {
             return sort(list, field, null);
         }
     
         /**
          * 对list中的元素进行排序.
          * 
          * @param list 排序集合
          * @param field 排序字段
          * @param sort 排序方式: SortList.DESC(降序) SortList.ASC(升序).
          */
         @SuppressWarnings("unchecked")
         public static List<?> sort(List<?> list, final String field,final String sort) {
             Collections.sort(list, new Comparator() {
                 public int compare(Object a, Object b) {
                     int ret = 0;
                     try {
                         Field f = a.getClass().getDeclaredField(field);
                         f.setAccessible(true);
                         Class<?> type = f.getType();
     
                         if (type == int.class) {
                             ret = Integer.compare(f.getInt(a), f
                                     .getInt(b));
                         } else if (type == double.class) {
                             ret = Double.compare(f.getDouble(a), f
                                     .getDouble(b));
                         } else if (type == long.class) {
                             ret = Long.compare(f.getLong(a), f
                                     .getLong(b));
                         } else if (type == float.class) {
                             ret = Float.compare(f.getFloat(a), f
                                     .getFloat(b));
                         } else if (type == Date.class) {
                             ret = ((Date) f.get(a)).compareTo((Date) f.get(b));
                         } else if (isImplementsOf(type, Comparable.class)) {
                             ret = ((Comparable) f.get(a)).compareTo(f
                                     .get(b));
                         } else {
                             ret = String.valueOf(f.get(a)).compareTo(
                                     String.valueOf(f.get(b)));
                         }
     
                     } catch (SecurityException | NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
                         e.printStackTrace();
                     }
                     if (sort != null && sort.equalsIgnoreCase(DESC)) {
                         return -ret;
                     } else {
                         return ret;
                     }
                 }
             });
             return list;
         }
     
         /**
          * 对list中的元素按fields和sorts进行排序,
          * fields[i]指定排序字段,sorts[i]指定排序方式.如果sorts[i]为空则默认按升序排列.
          * 
          * @param list
          * @param fields
          * @param sorts
          */
         @SuppressWarnings("unchecked")
         public static List<?> sort(List<?> list, String[] fields, String[] sorts) {
             if (fields != null && fields.length > 0) {
                 for (int i = fields.length - 1; i >= 0; i--) {
                     final String field = fields[i];
                     String tmpSort = ASC;
                     if (sorts != null && sorts.length > i && sorts[i] != null) {
                         tmpSort = sorts[i];
                     }
                     final String sort = tmpSort;
                     Collections.sort(list, new Comparator() {
                         public int compare(Object a, Object b) {
                             int ret = 0;
                             try {
                                 Field f = a.getClass().getDeclaredField(field);
                                 f.setAccessible(true);
                                 Class<?> type = f.getType();
                                 if (type == int.class) {
                                     ret = ((Integer) f.getInt(a))
                                             .compareTo(f.getInt(b));
                                 } else if (type == double.class) {
                                     ret = ((Double) f.getDouble(a))
                                             .compareTo(f.getDouble(b));
                                 } else if (type == long.class) {
                                     ret = ((Long) f.getLong(a)).compareTo(f
                                             .getLong(b));
                                 } else if (type == float.class) {
                                     ret = ((Float) f.getFloat(a))
                                             .compareTo(f.getFloat(b));
                                 } else if (type == Date.class) {
                                     ret = ((Date) f.get(a)).compareTo((Date) f
                                             .get(b));
                                 } else if (isImplementsOf(type, Comparable.class)) {
                                     ret = ((Comparable) f.get(a))
                                             .compareTo(f.get(b));
                                 } else {
                                     ret = String.valueOf(f.get(a)).compareTo(
                                             String.valueOf(f.get(b)));
                                 }
     
                             } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
                                 e.printStackTrace();
                             }
     
                             if (sort != null && sort.equalsIgnoreCase(DESC)) {
                                 return -ret;
                             } else {
                                 return ret;
                             }
                         }
                     });
                 }
             }
             return list;
         }
     
         /**
          * 默认按正序排列
          * 
          * @param list
          * @param method
          */
         public static List<?> sortByMethod(List<?> list, final String method) {
             return sortByMethod(list, method, null);
         }
     
         @SuppressWarnings("unchecked")
         public static List<?> sortByMethod(List<?> list, final String method,final String sort) {
             Collections.sort(list, new Comparator() {
                 public int compare(Object a, Object b) {
                     int ret = 0;
                     try {
                         Method m = a.getClass().getMethod(method, null);
                         m.setAccessible(true);
                         Class<?> type = m.getReturnType();
                         if (type == int.class) {
                             ret = ((Integer) m.invoke(a, null))
                                     .compareTo((Integer) m.invoke(b, null));
                         } else if (type == double.class) {
                             ret = ((Double) m.invoke(a, null)).compareTo((Double) m
                                     .invoke(b, null));
                         } else if (type == long.class) {
                             ret = ((Long) m.invoke(a, null)).compareTo((Long) m
                                     .invoke(b, null));
                         } else if (type == float.class) {
                             ret = ((Float) m.invoke(a, null)).compareTo((Float) m
                                     .invoke(b, null));
                         } else if (type == Date.class) {
                             ret = ((Date) m.invoke(a, null)).compareTo((Date) m
                                     .invoke(b, null));
                         } else if (isImplementsOf(type, Comparable.class)) {
                             ret = ((Comparable) m.invoke(a, null))
                                     .compareTo(m.invoke(b, null));
                         } else {
                             ret = String.valueOf(m.invoke(a, null)).compareTo(
                                     String.valueOf(m.invoke(b, null)));
                         }
     
                         if (isImplementsOf(type, Comparable.class)) {
                             ret = ((Comparable) m.invoke(a, null))
                                     .compareTo(m.invoke(b, null));
                         } else {
                             ret = String.valueOf(m.invoke(a, null)).compareTo(
                                     String.valueOf(m.invoke(b, null)));
                         }
     
                     } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ne) {
                         ne.printStackTrace();
                     }
     
                     if (sort != null && sort.toLowerCase().equals(DESC)) {
                         return -ret;
                     } else {
                         return ret;
                     }
                 }
             });
             return list;
         }
     
         @SuppressWarnings("unchecked")
         public static List<?> sortByMethod(List<?> list, final String methods[],final String sorts[]) {
             if (methods != null && methods.length > 0) {
                 for (int i = methods.length - 1; i >= 0; i--) {
                     final String method = methods[i];
                     String tmpSort = ASC;
                     if (sorts != null && sorts.length > i && sorts[i] != null) {
                         tmpSort = sorts[i];
                     }
                     final String sort = tmpSort;
                     Collections.sort(list, new Comparator() {
                         public int compare(Object a, Object b) {
                             int ret = 0;
                             try {
                                 Method m = a.getClass().getMethod(method, null);
                                 m.setAccessible(true);
                                 Class<?> type = m.getReturnType();
                                 if (type == int.class) {
                                     ret = ((Integer) m.invoke(a, null))
                                             .compareTo((Integer) m.invoke(b, null));
                                 } else if (type == double.class) {
                                     ret = ((Double) m.invoke(a, null))
                                             .compareTo((Double) m.invoke(b, null));
                                 } else if (type == long.class) {
                                     ret = ((Long) m.invoke(a, null))
                                             .compareTo((Long) m.invoke(b, null));
                                 } else if (type == float.class) {
                                     ret = ((Float) m.invoke(a, null))
                                             .compareTo((Float) m.invoke(b, null));
                                 } else if (type == Date.class) {
                                     ret = ((Date) m.invoke(a, null))
                                             .compareTo((Date) m.invoke(b, null));
                                 } else if (isImplementsOf(type, Comparable.class)) {
                                     ret = ((Comparable) m.invoke(a, null))
                                             .compareTo(m.invoke(b,
                                                     null));
                                 } else {
                                     ret = String.valueOf(m.invoke(a, null))
                                             .compareTo(
                                                     String.valueOf(m
                                                             .invoke(b, null)));
                                 }
     
                             } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ne) {
                                 ne.printStackTrace();
                             }
     
                             if (sort != null && sort.toLowerCase().equals(DESC)) {
                                 return -ret;
                             } else {
                                 return ret;
                             }
                         }
                     });
                 }
             }
             return list;
         }
     
         /**
          * 判断对象实现的所有接口中是否包含szInterface
          * 
          * @param clazz
          * @param szInterface
          */
         public static boolean isImplementsOf(Class<?> clazz, Class<?> szInterface) {
             boolean flag = false;
     
             Class<?>[] face = clazz.getInterfaces();
             for (Class<?> c : face) {
                 if (c == szInterface) {
                     flag = true;
                 } else {
                     flag = isImplementsOf(c, szInterface);
                 }
             }
     
             if (!flag && null != clazz.getSuperclass()) {
                 return isImplementsOf(clazz.getSuperclass(), szInterface);
             }
             return flag;
         }
      }
    

    main 方法测试

     	public static void main(String[] args) throws Exception {
             List<Person> list = new ArrayList<Person>();
     
             list.add(new Person("zhangsan", "b", 18));
             list.add(new Person("zhangsi", "b", 28));
             list.add(new Person("lisi", "d", 20));
             list.add(new Person("wangwu", "d", 22));
             System.out.println("-----------排序前---------------");
             for (Person p : list) {
                 System.out.println(p.toString());
             }
             System.out.println();
             // 按age正序排序,注意结果排完后是1,2,3,11. 不是1,11,2,3(如果是String类型正序排序是这样)
             CollectionsUtil.sort(list, "age", null);
             System.out.println("---------测试Integer和正序,按age正序排序-----------------");
             for (Person p : list) {
                 System.out.println(p.toString());
             }
             System.out.println();
             // 按id倒序
             CollectionsUtil.sort(list, "userName", CollectionsUtil.DESC);
             System.out.println("--------测试int和倒序,按id倒序------------------");
             for (Person p : list) {
                 System.out.println(p.toString());
             }
             System.out.println();
     
             // 先按userName正序排序,再按age正序排序
             CollectionsUtil.sort(list, new String[] { "userName", "age" }, new String[] {});
             System.out
                     .println("---------测试多个排序字段,先按userName正序,userName相同时再按age正序-----------------");
             for (Person p : list) {
                 System.out.println(p.toString());
             }
             System.out.println();
     
             // 先按userName正序排序,再按id倒序排序
             CollectionsUtil.sort(list, new String[] { "userName", "age" }, new String[] {
                     CollectionsUtil.ASC, CollectionsUtil.DESC });
             System.out
                     .println("---------测试多个排序字段,先按userName正序,userName相同时再按age倒序-----------------");
             for (Person p : list) {
                 System.out.println(p.toString());
             }
             System.out.println();
     
             // sortByMethod
             CollectionsUtil.sortByMethod(list, "getAge", null);
             System.out
                     .println("---------测试sortByMethod,按getAge方法正序-----------------");
             for (Person p : list) {
                 System.out.println(p.toString());
             }
             System.out.println();
         }
    

    测试结果:
    在这里插入图片描述
    小结:
    另外,还可以在此基础上根据不同的业务需求进行更改和扩展。关于异常的问题,在这里只是做了一个简单的处理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值