按对象的两个字段排序.爪哇 [英] Sorting by two fields of object. Java

查看:80
本文介绍了按对象的两个字段排序.爪哇的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想按日期和名称排序.例如,我有这样的日期

I want to sort by date and name. For example I have date like this

2019 01 01 "CCCC"
2019 02 01 "Aaaa"
2019 03 01 "CCC"
2019 02 01 "BBBB"
2019 03 01 "Aaaa"
2019 01 01 "Aaaa"

我需要按月份(和年份)和字母排序,例如,它必须像这样:

I need to sort by month (and year) and alphabet, for example it must be like this:

2019 01 01 "Aaaa"
2019 01 01 "CCCC"
2019 02 01 "Aaaa"
2019 02 01 "BBBB"
2019 03 01 "Aaaa"
2019 03 01 "CCC"

我写了这样的代码:

Collections.sort(mainList, new Comparator<DocSet>() {

            public int compare(DocSet o1, DocSet o2) {
                SimpleDateFormat sdf = new SimpleDateFormat(Until.DATE_FORMAT);

                Calendar c1 = null;
                try {
                    String docSetDate1 = ((DocSet) o1).getDate();
                    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
                    c1 = Calendar.getInstance();
                    c1.setTime(sdf.parse(docSetDate1));
                }catch (Exception e){}

                Calendar c2 = null;
                try {
                    String docSetDate2 = ((DocSet) o2).getDate();
                    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
                    c2 = Calendar.getInstance();
                    c2.setTime(sdf.parse(docSetDate2));
                }catch (Exception e){}

                int sComp = c1.compareTo(c2);

                if (sComp != 0) {
                    return sComp;
                }

                String company_name1 = o1.getCompany_name();
                String company_name2 = o2.getCompany_name();

                return company_name1.compareTo(company_name2);
            }
        });

但是它仅按日期排序,就像这样:

But it is sorting by date only, like this:

2019 01 01 "CCCC"
2019 01 01 "Aaaa"
2019 02 01 "Aaaa"
2019 02 01 "BBBB"
2019 03 01 "CCC"
2019 03 01 "Aaaa"

更新如何按月(和年)和字母排序?我得到的数据必须是这样的:

UPDATE How can I by month (and year) and alphabet? My resulting data must be like this:

2019 01 01 "Aaaa"
2019 01 01 "CCCC"
2019 02 01 "Aaaa"
2019 02 01 "BBBB"
2019 03 01 "Aaaa"
2019 03 01 "CCC"

推荐答案

三点:

  1. 在您的日期和时间工作中,请使用现代Java日期和时间API java.time. SimpleDateFormat Date 类的设计很差,而且已经过时,尤其是前者非常麻烦.
  2. 不要将日期作为字符串保留在对象中.保留适当的日期时间对象,例如 LocalDate LocalDateTime .
  3. 从Java 8开始,要对多个字段进行排序,请使用 Comparator.comparing() .thenComparing()来实现更简单,更简短的代码,并且首先也是最不容易出错的代码
  1. Do use java.time, the modern Java date and time API, for your date and time work. The SimpleDateFormat and Date classes are poorly designed and long outdated, the former in particular notoriously troublesome.
  2. Don’t keep your dates as strings in your objects. Keep proper date-time objects such as LocalDate or LocalDateTime.
  3. For sorting on multiple fields since Java 8 use Comparator.comparing() and .thenComparing() for much simpler and terser and first and foremost less error-prone code.

在代码中:

    List<DocSet> mainList = Arrays.asList(
            new DocSet(LocalDate.of(2019, Month.JANUARY, 1), "CCCC"),
            new DocSet(LocalDate.of(2019, Month.FEBRUARY, 1), "Aaaa"),
            new DocSet(LocalDate.of(2019, Month.MARCH, 1), "CCC"),
            new DocSet(LocalDate.of(2019, Month.FEBRUARY, 1), "BBBB"),
            new DocSet(LocalDate.of(2019, Month.MARCH, 1), "Aaaa"),
            new DocSet(LocalDate.of(2019, Month.JANUARY, 1), "Aaaa"));

    Collections.sort(mainList,
            Comparator.comparing(DocSet::getDate).thenComparing(DocSet::getCompanyName));

    mainList.forEach(System.out::println);

此代码段的输出为:

2019-01-01 Aaaa
2019-01-01 CCCC
2019-02-01 Aaaa
2019-02-01 BBBB
2019-03-01 Aaaa
2019-03-01 CCC

您会注意到,对象首先按日期排序,然后按公司名称排序.

You notice that the objects have been sorted first by date, next by company name.

如果要对公司名称进行不区分大小写的排序,请使用

If you want case-insensitive sorting of company names, use

    Collections.sort(mainList,
            Comparator.comparing(DocSet::getDate)
                      .thenComparing(DocSet::getCompanyName, String::compareToIgnoreCase));

您的代码出了什么问题?

您的代码可以按照您希望的方式工作.您在注释中链接的图像说明,对象首先按日期和时间(190103120010之前的190101120010)排序,然后按公司名称(Abdc1之前的AAAAAAAAAbdc1)排序.

What went wrong in your code?

Your code works as you say you want it to. The image that you linked to in a comment documents that your objects are sorted first by date and time (190101120010 before 190103120010), next by company name (AAAAAAAAAbdc1 before Abdc1).

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Your own image documenting that your sorting is correct, again

为了完整的示例,这里是我在上面的代码中使用的 DocSet 类:

For the sake of a complete example here is the DocSet class that I have used in the above code:

public class DocSet {

    LocalDate date;
    String companyName;

    public DocSet(LocalDate date, String companyName) {
        this.date = date;
        this.companyName = companyName;
    }

    public LocalDate getDate() {
        return date;
    }

    public String getCompanyName() {
        return companyName;
    }

    @Override
    public String toString() {
        return "" + date + ' ' + companyName;
    }
}

这篇关于按对象的两个字段排序.爪哇的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆