问题
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:
- Do use java.time, the modern Java date and time API, for your date and time work. The
SimpleDateFormatandDateclasses are poorly designed and long outdated, the former in particular notoriously troublesome. - Don’t keep your dates as strings in your objects. Keep proper date-time objects such as
LocalDateorLocalDateTime. - 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