java 无论如何,将空值排序到底部的好方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1261934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Nice general way to sort nulls to the bottom, regardless?
提问by Carl Manaster
I'm writing some custom Comparators, and I'd like them to push null items to the bottom of the list, regardless of whether I'm sorting ascending or descending. What's a good strategy or pattern for approaching this?
我正在编写一些自定义比较器,我希望它们将空项目推到列表的底部,无论我是按升序还是降序排序。解决这个问题的好策略或模式是什么?
Offhand:
副手:
- Simply write separate ascending and descending comparators, sharing code where possible
- Delegate null handling to another class, either by throwing an NPE or by calling it explicitly
- Include an ascending flag and put conditional logic in it to navigate around the nulls
- Wrap regular comparators in a null-handling class
- 只需编写单独的升序和降序比较器,尽可能共享代码
- 将空处理委托给另一个类,通过抛出 NPE 或显式调用它
- 包含一个升序标志并在其中放置条件逻辑以在空值周围导航
- 将常规比较器包装在空处理类中
Any other strategies? I'd like to hear about any experiences with different approaches, and any pitfalls for the various strategies.
还有其他策略吗?我想听听使用不同方法的任何经验,以及各种策略的任何陷阱。
采纳答案by Jon Skeet
The last option appeals to me a lot. Comparators are really great to chain together. In particular you may well want to write a ReverseComparatoras well as a NullWrappingComparator.
最后一个选项对我很有吸引力。比较器非常适合链接在一起。特别是,您可能希望编写 aReverseComparator和NullWrappingComparator.
EDIT: You don't have to write this yourself. If you look at the Orderingclass in the Google Collections Libraryyou'll find this and all kinds of other goodies :)
编辑:你不必自己写这个。如果您查看Google Collections Library中的Ordering类,您会发现这个和其他各种好东西:)
EDIT: Going into more detail to show what I mean about ReverseComparator...
编辑:更详细地说明我的意思ReverseComparator......
One word of warning - in the implementation of a ReverseComparator, reverse the order of the arguments instead of negating the result, as otherwise Integer.MIN_VALUEis "reversed" to itself.
一个警告 - 在 a 的实现中ReverseComparator,反转参数的顺序而不是否定结果,否则Integer.MIN_VALUE会“反转”到它自己。
So this implementation is wrong (assuming originalis the comparator to reverse):
所以这个实现是错误的(假设original是要反转的比较器):
public int compare(T x, T y)
{
return -original.compare(x, y);
}
but this is right:
但这是对的:
public int compare(T x, T y)
{
return original.compare(y, x);
}
The reason is that we always want to reverse the comparison, but if original.compare(x, y)returns int.MIN_VALUE, then the bad comparer will alsoreturn int.MIN_VALUE, which is incorrect. This is due to the funny property that int.MIN_VALUE == -int.MIN_VALUE.
原因是,我们总是希望扭转比较,但如果original.compare(x, y)回报率int.MIN_VALUE,那么坏的比较器将还回int.MIN_VALUE,这是不正确。这是由于int.MIN_VALUE == -int.MIN_VALUE.
回答by dfa
I agree with Jon Skeet (it's so easy :). I tried to implement a very simple decorator:
我同意 Jon Skeet 的观点(这很简单:)。我试图实现一个非常简单的装饰器:
class NullComparators {
static <T> Comparator<T> atEnd(final Comparator<T> comparator) {
return new Comparator<T>() {
public int compare(T o1, T o2) {
if (o1 == null && o2 == null) {
return 0;
}
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
return comparator.compare(o1, o2);
}
};
}
static <T> Comparator<T> atBeginning(final Comparator<T> comparator) {
return Collections.reverseOrder(atEnd(comparator));
}
}
given a Comparator:
给定一个比较器:
Comparator<String> wrapMe = new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
and some test data:
和一些测试数据:
List<String> strings = Arrays.asList(null, "aaa", null, "bbb", "ccc", null);
you can sort with nulls at end:
您可以在末尾使用空值进行排序:
Collections.sort(strings, NullComparators.atEnd(wrapMe));
[aaa, bbb, ccc, null, null, null]
or at beginning:
或开始时:
Collections.sort(strings, NullComparators.atBeginning(wrapMe));
[null, null, null, ccc, bbb, aaa]
回答by Carl Manaster
Following up on dfa's answer - what I want is that the nulls sort at the end without affecting the order of the non-nulls. So I want something more along the lines of this:
跟进 dfa 的回答 - 我想要的是最后对空值进行排序而不影响非空值的顺序。所以我想要更多类似的东西:
public class NullComparatorsTest extends TestCase {
Comparator<String> forward = new Comparator<String>() {
public int compare(String a, String b) {
return a.compareTo(b);
}
};
public void testIt() throws Exception {
List<String> strings = Arrays.asList(null, "aaa", null, "bbb", "ccc", null);
Collections.sort(strings, NullComparators.atEnd(forward));
assertEquals("[aaa, bbb, ccc, null, null, null]", strings.toString());
Collections.sort(strings, NullComparators.atBeginning(forward));
assertEquals("[null, null, null, aaa, bbb, ccc]", strings.toString());
}
}
public class NullComparators {
public static <T> Comparator<T> atEnd(final Comparator<T> comparator) {
return new Comparator<T>() {
public int compare(T a, T b) {
if (a == null && b == null)
return 0;
if (a == null)
return 1;
if (b == null)
return -1;
return comparator.compare(a, b);
}
};
}
public static <T> Comparator<T> atBeginning(final Comparator<T> comparator) {
return new Comparator<T>() {
public int compare(T a, T b) {
if (a == null && b == null)
return 0;
if (a == null)
return -1;
if (b == null)
return 1;
return comparator.compare(a, b);
}
};
}
}
Full credit to dfa, though - this is just a minor modification of his work.
不过,完全归功于 dfa - 这只是他工作的一个小修改。
回答by Ali Dehghani
In Java 8, you can use the Comparator.nullsLastand Comparator.nullsFirststatic methods to have more null-friendly comparators. Suppose you have a Fruitclass like the following:
在 Java 8 中,您可以使用 theComparator.nullsLast和Comparator.nullsFirststatic 方法来拥有更多对 null 友好的比较器。假设您有一个Fruit如下所示的类:
public class Fruit {
private final String name;
private final Integer size;
// Constructor and Getters
}
If you want to sort a bunch of fruits by their size and put the nulls at the end:
如果您想按大小对一堆水果进行排序并将nulls 放在末尾:
List<Fruit> fruits = asList(null, new Fruit("Orange", 25), new Fruit("Kiwi", 5));
You can simply write:
你可以简单地写:
Collections.sort(fruits, Comparator.nullsLast(Comparator.comparingInt(Fruit::getSize)));
And the result would be:
结果将是:
[Fruit{name='Kiwi', size=5}, Fruit{name='Orange', size=25}, null]
回答by Tim R
You could always use NullComparatorfrom commons-collections. It's been around longer than Google Collections.
你总是可以使用NullComparator来自 commons-collections。它的存在时间比 Google Collections 还长。

