Java 如何处理 compare() 中的空字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/128042/
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
What to do with null fields in compare()?
提问by Sébastien RoccaSerra
In Java, I use a class in which some fields can be null
. For example:
在 Java 中,我使用一个类,其中一些字段可以是null
. 例如:
class Foo {
String bar;
//....
}
I want to write a BarComparator for this class,
我想为这个类写一个 BarComparator,
private static class BarComparator
implements Comparator<Foo> {
public int compare( final Foo o1, final Foo o2 )
{
// Implementation goes here
}
}
Is there a standard way to deal with the fact that any of o1
, o2
, o1.bar
, o2.bar
can be null
, without writing lots of nested if
...else
?
是否有应对的事实,任何的标准方式o1
,o2
,o1.bar
,o2.bar
可null
,而无需编写大量的嵌套if
...... else
?
Cheers!
干杯!
采纳答案by Tom Hawtin - tackline
I guess you could wrap the call to the field compareTo method with a small static method to sort nulls high or low:
我想你可以用一个小的静态方法包装对字段 compareTo 方法的调用,以对空值进行高或低排序:
static <T extends Comparable<T>> int cp(T a, T b) {
return
a==null ?
(b==null ? 0 : Integer.MIN_VALUE) :
(b==null ? Integer.MAX_VALUE : a.compareTo(b));
}
Simple usage (multiple fields is as you would normally):
简单用法(多字段与您通常使用的一样):
public int compare( final Foo o1, final Foo o2 ) {
return cp(o1.field, o2.field);
}
回答by cagcowboy
I think early return statements would be the other alternative to lots of ifs
我认为早期的 return 语句将是许多 ifs 的另一种选择
e.g.
例如
if(o1==null) return x;
if(o2==null) return x;
if(o1.getBar()==null) return x;
if(o2.getBar()==null) return x;
// No null checks needed from this point.
回答by Matt
It depends on whether you consider a null entry to be a valid string value worth of comparison. is null < or > "apple". The only thing I could say for sure is that null == null. If you can define where null fits into the ordering then you can write the code appropriately.
这取决于您是否认为空条目是值得比较的有效字符串值。为空 < 或 > “苹果”。我唯一可以肯定的是 null == null。如果您可以定义 null 适合排序的位置,那么您可以适当地编写代码。
In this case I might choose to throw a NullPointerExcpetion or IllegalArgumentException and try to handle the null at a higher level by not putting it in the comparison in the first place.
在这种情况下,我可能会选择抛出 NullPointerExcpetion 或 IllegalArgumentException 并尝试通过不首先将其放入比较中来在更高级别处理空值。
回答by DJClayworth
The key thing here is to work out how you would like nulls to be treated. Some options are: a) assume nulls come before all other objects in sort order b) assume nulls come after all other objects in sort order c) treat null as equivalent to some default value d) treat nulls as error conditions. Which one you choose will depend entirely on the application you are working on.
这里的关键是弄清楚您希望如何处理空值。一些选项是:a) 假设空值在排序顺序中出现在所有其他对象之前 b) 假设空值在排序顺序中所有其他对象之后 c) 将空值视为等效于某个默认值 d) 将空值视为错误条件。您选择哪一个将完全取决于您正在处理的应用程序。
In the last case of course you throw an exception. For the others you need a four-way if/else case (about three minutes of coding one you've worked out what you want the results to be).
在最后一种情况下,您当然会抛出异常。对于其他情况,您需要一个四路 if/else 案例(大约三分钟的编码时间,您已经确定了您想要的结果)。
回答by Gregg
If you're using Google collections, you may find the Comparatorsclass helpful. If has helper methods for ordering nulls as either the greatest or least elements in the collection. You can use compound comparatorsto help reduce the amount of code.
如果您使用的是 Google 集合,您可能会发现Comparators类很有帮助。If 具有用于将空值排序为集合中最大或最少元素的辅助方法。您可以使用复合比较器来帮助减少代码量。
回答by Sébastien RoccaSerra
Thanks for the replies! The generic method and the Google Comparators look interesting.
感谢您的回复!泛型方法和 Google 比较器看起来很有趣。
And I found that there's a NullComparatorin the Apache Commons Collections(which we're currently using):
而且我发现,有一个NullComparator中的Apache Commons Collections中(这是我们目前正在使用):
private static class BarComparator
implements Comparator<Foo>
{
public int compare( final Foo o1, final Foo o2 )
{
// o1.bar & o2.bar nulleness is taken care of by the NullComparator.
// Easy to extend to more fields.
return NULL_COMPARATOR.compare(o1.bar, o2.bar);
}
private final static NullComparator NULL_COMPARATOR =
new NullComparator(false);
}
Note: I focused on the bar
field here to keep it to the point.
注意:我在bar
这里专注于该领域以保持重点。
回答by Martin Probst
You should not use the NullComparator the way you do - you're creating a new instance of the class for every comparison operation, and if e.g. you're sorting a list with 1000 entries, that will be 1000 * log2(1000) objects that are completely superfluous. This can quickly get problematic.
你不应该像你那样使用 NullComparator - 你正在为每个比较操作创建一个类的新实例,例如,如果你正在对一个包含 1000 个条目的列表进行排序,那将是 1000 * log2(1000) 个对象完全是多余的。这很快就会出现问题。
Either subclass it, or delegate to it, or simply implement your own null check - it's really not that complex:
要么继承它,要么委托给它,或者简单地实现你自己的空检查——它真的没有那么复杂:
private static class BarComparator
implements Comparator<Foo> {
private NullComparator delegate = new NullComparator(false);
public int compare( final Foo o1, final Foo o2 )
{
return delegate.compare(o1.bar, o2.bar);
}
}
回答by savanibharat
You can write your Comparator for it. Lets say you have a class Person with String name as private field. getName() and setName() method to access the field name. Below is the Comparator for class Person.
您可以为它编写比较器。假设您有一个以字符串名称作为私有字段的 Person 类。getName() 和 setName() 方法来访问字段名称。下面是类 Person 的比较器。
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
if (a == null) {
if (b == null) {
return 0;
}
return -1;
} else if (b == null) {
return 1;
}
return a.getName().compareTo(b.getName());
}
});
Update:
更新:
As of Java 8 you can use below API's for List.
从 Java 8 开始,您可以将以下 API 用于列表。
// Push nulls at the end of List
Collections.sort(subjects1, Comparator.nullsLast(String::compareTo));
// Push nulls at the beginning of List
Collections.sort(subjects1, Comparator.nullsFirst(String::compareTo));
回答by Wim Deblauwe
There is also the class org.springframework.util.comparator.NullSafeComparator
in the Spring Framework you can use.
org.springframework.util.comparator.NullSafeComparator
您可以使用 Spring Framework 中的类。
Example (Java 8):
示例(Java 8):
SortedSet<Foo> foos = new TreeSet<>( ( o1, o2 ) -> {
return new NullSafeComparator<>( String::compareTo, true ).compare( o1.getBar(), o2.getBar() );
} );
foos.add( new Foo(null) );
foos.add( new Foo("zzz") );
foos.add( new Foo("aaa") );
foos.stream().forEach( System.out::println );
This will print:
这将打印:
Foo{bar='null'}
Foo{bar='aaa'}
Foo{bar='zzz'}
回答by Mr.Ko?ak
Considering Customer as a POJO.My answer would be :
将客户视为 POJO。我的答案是:
Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId()));
Or
或者
Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo));