Sorting by two fields of object. Java

风流意气都作罢 提交于 2021-02-15 07:45:54

问题


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"

回答1:


Three points:

  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.

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

Links

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

The DocSet class I have used

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


来源:https://stackoverflow.com/questions/60561226/sorting-by-two-fields-of-object-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!