java对象比较排序

排序基础

在项目开发中,我们经常要对一组数据排序,或者升序或者降序, 在java中排序有多种方式,最土的方法就是自己写排序算法, 比如冒泡排序,快速排序,二叉树排序等,但一般不要自己写, jdk已经为我们提供了很多的 排序算法,我们采用拿来主义就成了。

在java中,要给数据排序,有两种实现方式,分别实现两个接口:

  1. 实现Comparable接口
  2. 实现Comparator接口

在JDK类库中,有一部分类实现了Comparable接口,如Integer Double和String等。

Comparable接口有一个comparTo(Object o)方法,它返回整数类型。 对于表达式x.compareTo(y), 如果返回值为0,则表示x和y相等, 如果返回值大于0,则表示x大于y, 如果返回值小于0,则表示x小于y.

alt

查看Comparable接口源码

public interface Comparable<T> {
    public int compareTo(T o);
}

举个例子

给公司职员排序,按照工号排序,先定义一个职员类,编写Employee类实现Comparable接口:

package hello;

import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

public class Employee implements Comparable<Employee>{
    // id是根据进入公司的先后顺序编码的
    private int id;
    // 姓名
    private String name;
    // 职位
    private Position position;
    
    public Employee(int id, String name, Position position) {
        super();
        this.id = id;
        this.name = name;
        this.position = position;
    }
    
    //按照id号排序,也就是资历的深浅排序
    @Override
    public int compareTo(Employee o) {
        // TODO Auto-generated method stub
        return new CompareToBuilder().append(id, o.id).toComparison();
    }
    
    @Override
    public String toString(){
         return ToStringBuilder.reflectionToString(this);
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Position getPosition() {
        return position;
    }

    public void setPosition(Position position) {
        this.position = position;
    }
}

这是一个简单的javabean,描述的是一个员工的基本信息, 其中id是员工编号,按照进入公司的先后顺序编码, position是岗位描述,表示是经理还是普通职员,这是一个枚举类型:

public enum Position {
  Boss, Manager,staff
}

职位有三个级别: Boss(老板), Manager(经理), Staff(职员)

按id排序

Employee类的compareTo()方法,是Comparable接口必须要实现的方法, 使用apach的工具类来实现,表明是按照id的自然序列排序的(升序)。 一切准备完毕,我们看看如何排序:

package hello;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class HelloWord {

    public static void main(String[] args) {
        List<Employee> list = new ArrayList<Employee>(5);
        // 一个老板
        list.add(new Employee(1001, "张三", Position.Boss));
        // 两个经理
        list.add(new Employee(1006, "赵四", Position.Manager));
        list.add(new Employee(1003, "王五", Position.Manager));
        // 两个职员
        list.add(new Employee(10002, "李六", Position.staff));
        list.add(new Employee(1005, "马牛", Position.staff));
        // 按照id排序,也就是按照资历深浅排序
        Collections.sort(list);
        for (Employee e : list) {
            System.out.println(e);
        }
    }
}

运行结果

hello.Employee@46244bb9[id=1001,name=张三,position=Boss]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@3e0a765c[id=1005,name=马牛,position=staff]
hello.Employee@7fbb6976[id=1006,name=赵四,position=Manager]
hello.Employee@6909037d[id=10002,name=李六,position=staff]

是按照id升序排列的,结果正确。

按职位排序

本着“领导为先”的理念,按职位从高到低排序, 先是老板,然后是经理,最后是普通职员, Employee已经是一个稳定类,为了一个排序功能修改它, 影响按照id排序,不是一个好办法。

Collections.sort()方法有一个重载方法sort(List list, Comparator<? super T> c), 有一个Comparator接口参数,我们实现这个接口:

//职位排序器
class PositionComparator implements Comparator<Employee>{
    @Override
    public int compare(Employee o1, Employee o2) {
        //按照职位降序排列
        return o1.getPosition().compareTo(o2.getPosition());
    }
}

创建了一个职位排序法,按职位高低排序,测试一下:

Collections.sort(list, new PositionComparator());
for (Employee e : list) {
    System.out.println(e);
}

运行结果

hello.Employee@46244bb9[id=1001,name=张三,position=Boss]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@7fbb6976[id=1006,name=赵四,position=Manager]
hello.Employee@3e0a765c[id=1005,name=马牛,position=staff]
hello.Employee@6909037d[id=10002,name=李六,position=staff]

按照职位排序,结果正确。

按照职位从低到高排序

为了照顾员工,需要按职位由低到高排序

两个办法:

  1. Collections.reverse(List<?> list)方法实现倒序排列
  2. Collections.sort(List<?> list,Collections.reverseOrder(new PositionComparator())也可以

用这两个方法来测试:

Collections.reverse(list);
for (Employee e : list) {
    System.out.println(e);
}

System.out.println("----");

Collections.sort(list,Collections.reverseOrder(new PositionComparator()));

for (Employee e : list) {
    System.out.println(e);
}

运行结果

hello.Employee@6909037d[id=10002,name=李六,position=staff]
hello.Employee@3e0a765c[id=1005,name=马牛,position=staff]
hello.Employee@7fbb6976[id=1006,name=赵四,position=Manager]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@46244bb9[id=1001,name=张三,position=Boss]
----
hello.Employee@6909037d[id=10002,name=李六,position=staff]
hello.Employee@3e0a765c[id=1005,name=马牛,position=staff]
hello.Employee@7fbb6976[id=1006,name=赵四,position=Manager]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@46244bb9[id=1001,name=张三,position=Boss]

按照职位由地到高排序,结果正确

先按职位排序,职位 相同按id排序

在compareTo或compare方法中先判断职位是否相等,职位相等再根据工号排序

修改Employee类的compareTo()方法为

@Override
public int compareTo(Employee o) {
    return new CompareToBuilder()
        .append(position, o.position)    //按照职位排序
        .append(o.id,id).toComparison(); //工号排序
}

排序代码:

Collections.sort(list);
for (Employee e : list) {
    System.out.println(e);
}

运行结果

hello.Employee@4d871a69[id=1001,name=张三,position=Boss]
hello.Employee@631803fb[id=1006,name=赵四,position=Manager]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@655538e5[id=1005,name=马牛,position=staff]
hello.Employee@20e0b1d6[id=1002,name=李六,position=staff]

总结

实现了Comparable接口类表明自身可比较,有了比较才能进行排序; Comparator接口是一个工具类接口,用作比较,与原类的逻辑没有关系;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值