Сортировка по двум полям объекта. Java - PullRequest
0 голосов
/ 06 марта 2020

Я хочу отсортировать по дате и имени. Например, у меня есть такая дата

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"

ОБНОВЛЕНИЕ Как я могу по месяцам (и годам) и алфавиту ? Мои итоговые данные должны быть такими:

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 Ответ

1 голос
/ 07 марта 2020

Три пункта:

  1. Используйте java .time, современный Java API даты и времени, для вашей работы с датой и временем. Классы SimpleDateFormat и Date плохо спроектированы и давно устарели, первые особенно печально известны.
  2. Не храните даты в виде строк в ваших объектах. Сохраняйте правильные объекты даты и времени, такие как LocalDate или LocalDateTime.
  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));

Что пошло не так в вашем коде?

Ваш код работает так, как вы хотите. Изображение, на которое вы ссылаетесь в комментарии, документирует, что ваши объекты отсортированы вначале по дате и времени (с 190101120010 до 190103120010), затем по названию компании (AAAAAAAAAbdc1 до Abdc1).

Ссылки

Класс 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...