[英]Sort a Map<String, Object> first on Object.property1 and then for each Object.property1, sort by Object.property2
I have used the below method to Sort a Map first on Object.property1 and then for each Object.property1, sort by Object.property2. 我使用下面的方法首先在Object.property1上对Map进行排序,然后对每个Object.property1进行排序,按Object.property2排序。
for example, 例如,
property1 = TaxIdNumber and property1 = TaxIdNumber和
property2 = ProviderName property2 = ProviderName
I was just wondering this can be done in a more shorter and precise manner. 我只是想知道这可以用更短更精确的方式完成。 Any help or suggestion would be appreciated.
任何帮助或建议将不胜感激。
private List<TestObject> sortByValue(final Map m) {
List<TestObject> values = new ArrayList<TestObject>();
values.addAll(m.values());
// First sort the list by Tax ID.
Collections.sort(values, new Comparator<TestObject>() {
public int compare(TestObject r1, TestObject r2) {
Long taxId1 = (r1 == null ? null : r1.getTaxIdNumber());
Long taxId2 = (r2 == null ? null : r2.getTaxIdNumber());
if (taxId1 == null || taxId2 == null) {
return 0;
}
return taxId1.compareTo(taxId2);
}
});
// Then sort the list by Provider name.
Collections.sort(values, new Comparator<TestObject>() {
public int compare(TestObject r1, TestObject r2) {
String name1 = (r1 == null ? null : r1.getProviderName());
String name2 = (r2 == null ? null : r2.getProviderName());
if (name1 == null || name2 == null) {
return 0;
}
if (r1.getTaxIdNumber() == r2.getTaxIdNumber()) {
return name1.compareTo(name2);
} else {
return 0;
}
}
});
return values;
}
You only need one comparator. 你只需要一个比较器。 first compare the taxids.
首先比较出租车。 If they are unequal return -1 or 1 as appropriate.
如果它们是不等的,则返回-1或1。 If they are equals, then compare the provider name.
如果它们是等于,则比较提供者名称。
something like: 就像是:
Collections.sort(values, new Comparator<TestObject>() {
public int compare(TestObject r1, TestObject r2) {
Long taxId1 = (r1 == null ? null : r1.getTaxIdNumber());
Long taxId2 = (r2 == null ? null : r2.getTaxIdNumber());
if (taxId1 == null || taxId2 == null) {
return 0;
}
int cmp = taxId1.compareTo(taxId2);
if (cmp != 0)
return cmp;
String name1 = (r1 == null ? null : r1.getProviderName());
String name2 = (r2 == null ? null : r2.getProviderName());
if (name1 == null || name2 == null) {
return 0;
}
return name1.compareTo(name2);
}
});
Your null-handling violates the contract of compare
, as you deem null
equal to any other value, while the JavaDoc writes: 您的null处理违反了
compare
的约定,因为您认为null
等于任何其他值,而JavaDoc写道:
Compares its two arguments for order.
比较它的两个参数的顺序。 Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
返回负整数,零或正整数,因为第一个参数小于,等于或大于第二个参数。
and in particular: 特别是:
Finally, the implementor must ensure that
compare(x, y)==0
implies thatsgn(compare(x, z))
==sgn(compare(y, z))
for all z.最后,实现者必须确保
compare(x, y)==0
意味着所有z的sgn(compare(x, z))
==sgn(compare(y, z))
。
which your code fails to accomplish for x = null
, y = "a"
, z = "b"
. 您的代码无法完成
x = null
, y = "a"
, z = "b"
。
Therefore, if any objects or properties in the list are null
, the list may not be sorted correctly. 因此,如果列表中的任何对象或属性为
null
,则列表可能无法正确排序。
That being said, I wonder if the list may really contain null
values or properties? 话虽如此,我想知道列表是否真的包含
null
值或属性? If not, I'd remove all null
checks and end up with 如果没有,我将删除所有
null
检查并最终结束
Collections.sort(list, new Comparator<TestObject>() {
@Override public int compare(TestObject o1, TestObject o2) {
int c = o1.getTaxIdNumber().compareTo(o2.getTaxIdNumber);
if (c != 0) {
return c;
}
return o1.getProviderName().compareTo(o2.getProviderName());
}
}
If the list may contain null
objects or properties, you must define whether the null
values come first or last, and extend the comparator accordingly: 如果列表可能包含
null
对象或属性,则必须定义null
值是先到还是最后,并相应地扩展比较器:
Collections.sort(list, new Comparator<TestObject>() {
@Override public int compare(TestObject o1, TestObject o2) {
// insert null-checks for o1, o2 here
int c = cmp(getTaxIdNumber(), o2.getTaxIdNumber());
if (c != 0) {
return c;
}
return cmp(o1.getProviderName(), o2.getProviderName());
}
private <T extends Comparable<? super T>> cmp(T o1, T o2) {
if (o1 == o2) {
return 0;
else if (o1 == null) {
return -1;
} else if (o2 == null) {
return 1;
} else {
return o1.compareTo(o2);
}
}
}
Now this is quite a bit of repetitive and tricky code, which is why the folks over at Apache wrote the CompareToBuilder . 现在这是一个相当多的重复和棘手的代码,这就是为什么Apache的人写了CompareToBuilder 。 With that API, you can simply write:
使用该API,您只需编写:
@Override int compare(TestObject r1, TestObject r2) {
// insert null checks for r1 and r2 here - if you really need them
return new CompareToBuilder()
.append(r1.getTaxIdNumber(), r2.getTaxIdNumber())
.append(r1.getProviderName(), r2.getProviderName())
.toComparison();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.