简体   繁体   English

按对象的两个字段排序。 爪哇

[英]Sorting by two fields of object. Java

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"

I have written code like this:我写过这样的代码:

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"

Three points:三点:

  1. Do use java.time, the modern Java date and time API, for your date and time work.请务必使用 java.time,现代 Java 日期和时间 API,进行日期和时间工作。 The SimpleDateFormat and Date classes are poorly designed and long outdated, the former in particular notoriously troublesome. SimpleDateFormatDate类的设计很差,而且已经过时了,前者尤其麻烦。
  2. Don't keep your dates as strings in your objects.不要将日期作为字符串保存在对象中。 Keep proper date-time objects such as LocalDate or LocalDateTime .保留适当的日期时间对象,例如LocalDateLocalDateTime
  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.自 Java 8 以来,为了对多个字段进行排序,请使用Comparator.comparing().thenComparing()来获得更简单、更简洁、最重要的是更不容易出错的代码。

In 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);

The output from this snippet is:此代码段的输出是:

 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));

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).您在评论中链接到的图像记录了您的对象首先按日期和时间排序(190101120010 在 190103120010 之前),其次是公司名称(在 Abdc1 之前的 AAAAAAAAAbdc1)。

Links链接

The DocSet class I have used我使用过的 DocSet 类

For the sake of a complete example here is the DocSet class that I have used in the above code:为了一个完整的例子,这里是我在上面的代码中使用的DocSet类:

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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM