问题
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
SimpleDateFormat
andDate
classes 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
LocalDate
orLocalDateTime
. - 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