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

时间:2020-03-06 09:35:48

标签: java sorting collections

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

#include <algorithm>
#include <vector>
#include <iostream>

void print(const std::vector<int>& s)
{
    for (int i : s) {
        std::cout << i;
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> s = {1, 2, 3, 4};
    std::sort(s.begin(), s.end());
    do {
        print(s);
    } while(std::next_permutation(s.begin(), s.end()));
}

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

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

我写了这样的代码:

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

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

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

1 个答案:

答案 0 :(得分:1)

三点:

  1. 在您的日期和时间工作中,请使用现代Java日期和时间API java.time。 SimpleDateFormatDate类的设计很差,而且已经过时,特别是前者非常麻烦。
  2. 不要将日期作为字符串保留在对象中。保留适当的日期时间对象,例如LocalDateLocalDateTime
  3. 从Java 8开始,为了在多个字段上进行排序,使用Comparator.comparing().thenComparing()来简化和简化代码,并且首先也是最不容易出错的代码。

在代码中:

    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

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

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

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

您的代码出了什么问题?

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

链接

我使用的DocSet类

为了完整的示例,这里是我在上面的代码中使用的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;
    }
}