Comparator<T>实现自定义排序

应用目的

不在SQL中进行order by排序,而在Java代码中对某一字段进行排序,目的是为了缓解数据库的查询压力

源码

外比较器
java.util.Comparator

public interface Comparator<T> {
    /**
     * Compares its two arguments for order.  
     * Returns a negative integer,zero, or a positive integer 
     * as the first argument is less than, equal to, or greater than the second.
     **/
    int compare(T o1, T o2);
}

项目例子

ComparatorDateTool源码

public class ComparatorTool implements Comparator<CourierInfo> {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public int compare(CourierInfo t1, CourierInfo t2) {
        if ((t1==null && t2==null) ||
                (StringUtils.isBlank(t1.getSignTime()) && StringUtils.isBlank(t2.getSignTime()))){
            return 0;
        }
        if(t1==null || StringUtils.isBlank(t1.getSignTime())){
            return 1;
        }
        if(t2==null || StringUtils.isBlank(t2.getSignTime())){
            return -1;
        }
        Date d1, d2;
        try {
            d1 = format.parse(t1.getSignTime());
            d2 = format.parse(t2.getSignTime());
        } catch (Throwable e) {
            // 解析出错,则不进行排序
            return 0;
        }
        return d2.compareTo(d1);
    }

}

ConsignDTO源码

package com.forezp;

public class ConsignDTO {

	public String scantime; // 扫描时间

	public String getScantime() {
		return scantime;
	}
	public void setScantime(String scantime) {
		this.scantime = scantime;
	}
	@Override
	public String toString() {
		return "ConsignDTO [scantime=" + scantime + "]";
	}
 
}

DateStringDescTest源码

package com.forezp;

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

/**
 * 揽件扫描时间按时间降序排序,最近的日期显示在上面
 */
public class DateStringDescTest {

	public static void main(String[] args) {
		List<ConsignDTO> list = new ArrayList<ConsignDTO>();
		
		ConsignDTO teacher = new ConsignDTO();
		teacher.setScantime("2018/6/8 10:00:00");
		ConsignDTO teacher2 = new ConsignDTO();
		teacher2.setScantime("2018/6/2 10:00:00");
		ConsignDTO teacher3 = new ConsignDTO();
		teacher3.setScantime("2018/7/10 12:10:00");
		ConsignDTO teacher4 = new ConsignDTO();
		teacher4.setScantime("2018/7/10 16:00:00");
		
		list.add(teacher);
		list.add(teacher2);
		list.add(teacher3);
		list.add(teacher4);
		// 排序前
		System.out.println("=========排序前===========");
		list.forEach(t -> System.out.println(t.toString()));
		System.out.println("=========排序后===========");
		ComparatorDateTool c = new ComparatorDateTool();
		Collections.sort(list, c);
		list.forEach(t -> System.out.println(t.toString()));
		
	}
}

运行结果

=========排序前===========
ConsignDTO [scantime=2018/6/8 10:00:00]
ConsignDTO [scantime=2018/6/2 10:00:00]
ConsignDTO [scantime=2018/7/10 12:10:00]
ConsignDTO [scantime=2018/7/10 16:00:00]
=========排序后===========
ConsignDTO [scantime=2018/7/10 16:00:00]
ConsignDTO [scantime=2018/7/10 12:10:00]
ConsignDTO [scantime=2018/6/8 10:00:00]
ConsignDTO [scantime=2018/6/2 10:00:00]

简单写法

List tracesT = new ArrayList();
tracesT.add(baoTracesT);
Collections.sort(tracesT, new Comparator<TaoBaoTraces>() {
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private Date getBirthday(TaoBaoTraces m) {
		if ((m == null) || (m.getTime() == null))
			return null;
		try {
			return this.sdf.parse(m.getTime());
		} catch (ParseException e) {
		}
		return null;
	}

	public int compare(TaoBaoTraces o1, TaoBaoTraces o2) {
		Date d1 = getBirthday(o1);
		Date d2 = getBirthday(o2);
		if ((d1 == null) && (d2 == null))
			return 0;
		if (d1 == null)
			return -1;
		if (d2 == null)
			return 1;
		return d1.compareTo(d2);
	}
});

常见报错

报错信息

java.lang.IllegalArgumentException: Comparison method violates its general contract!

解决方案

  • 选择使用老版本的排序方法,在代码前面加上这么一句
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
  • 判断排序两个相等返回0

可以用对象的compareTo方法,或者自己考虑相等的情况

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里给出一个使用 `Comparable` 和 `Comparator` 接口的示例代码,可以实现您的要求: ```java import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ScoreSorter extends JFrame implements ActionListener { JTextField scoreField; JRadioButton ascBtn, descBtn; JButton sortBtn; public ScoreSorter() { initUI(); } private void initUI() { setTitle("Score Sorter"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(300, 150); JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3, 1)); JPanel scorePanel = new JPanel(); JLabel scoreLabel = new JLabel("Scores:"); scoreField = new JTextField(20); scorePanel.add(scoreLabel); scorePanel.add(scoreField); JPanel orderPanel = new JPanel(); JLabel orderLabel = new JLabel("Order:"); ascBtn = new JRadioButton("Ascending"); descBtn = new JRadioButton("Descending"); ButtonGroup group = new ButtonGroup(); group.add(ascBtn); group.add(descBtn); orderPanel.add(orderLabel); orderPanel.add(ascBtn); orderPanel.add(descBtn); JPanel buttonPanel = new JPanel(); sortBtn = new JButton("Sort"); sortBtn.addActionListener(this); buttonPanel.add(sortBtn); panel.add(scorePanel); panel.add(orderPanel); panel.add(buttonPanel); add(panel); setVisible(true); } public static void main(String[] args) { new ScoreSorter(); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == sortBtn) { String[] scores = scoreField.getText().split(","); List<Integer> intScores = new ArrayList<>(); for (String score : scores) { intScores.add(Integer.parseInt(score.trim())); } if (ascBtn.isSelected()) { Collections.sort(intScores); } else { Collections.sort(intScores, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); } }); } JOptionPane.showMessageDialog(this, intScores.toString()); } } } ``` 这个程序同样使用了 Swing 组件来构建 GUI,可以通过文本框输入多个分数,然后通过单选按钮选择是从小到大排列还是从大到小排列,最后点击按钮可以输出排列结果。在程序中,我们使用了 `Comparable` 和 `Comparator` 接口来比较分数大小,如果选择了从大到小排列,那么我们需要使用一个自定义的 `Comparator` 对象来实现排序。在这个示例中,我们使用了匿名内部类来创建 `Comparator` 对象,实现了 `compare()` 方法,该方法将会按照从大到小的顺序来比较分数大小。最终,我们将排序结果用 `JOptionPane` 显示出来。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值