在Java中,我使用的是一些类,其中某些字段可以是null
。例如:
class Foo {
String bar;
//....
}
我想为这个类编写一个BarComparator,
private static class BarComparator
implements Comparator<Foo> {
public int compare( final Foo o1, final Foo o2 )
{
// Implementation goes here
}
}
是否有一种标准方法可以处理o1
,o2
,o1.bar
,o2.bar
中的任何一个null
都可以{0}}的事实嵌套if
... else
?
干杯!
答案 0 :(得分:36)
我猜你可以用一个小的静态方法来调用字段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));
}
简单用法(多个字段与通常一样):
public int compare( final Foo o1, final Foo o2 ) {
return cp(o1.field, o2.field);
}
答案 1 :(得分:8)
感谢您的回复!通用方法和Google Comparators看起来很有趣。
我发现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);
}
注意:我专注于此处的bar
字段以保持其重要性。
答案 2 :(得分:6)
这取决于您是否将null条目视为值得比较的有效字符串值。是null&lt;或者&gt; “苹果”。我唯一可以肯定的是null == null。如果您可以定义null适合排序的位置,那么您可以适当地编写代码。
在这种情况下,我可能会选择抛出NullPointerExcpetion或IllegalArgumentException,并尝试在更高级别处理null,而不是首先将它放在比较中。
答案 3 :(得分:3)
您可以为它编写比较器。假设您有一个具有String名称的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());
}
});
更新
从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));
答案 4 :(得分:2)
这里的关键是要弄清楚如何处理空值。一些选项是:a)假设在排序顺序中所有其他对象之前出现空值b)假设在排序顺序中所有其他对象之后出现空值c)将null视为等效于某个默认值d)将空值视为错误条件。您选择哪一个完全取决于您正在使用的应用程序。
在最后一种情况下,你会抛出异常。对于其他人,你需要一个四向if / else的情况(大约三分钟的编码,你已经找到了你想要的结果)。
答案 5 :(得分:2)
如果您使用的是Google系列,则可能会发现Comparators课程很有帮助。如果有帮助方法,则将空值排序为集合中的最大元素或最小元素。您可以使用compound comparators来减少代码量。
答案 6 :(得分:2)
您可以使用Spring Framework中的类org.springframework.util.comparator.NullSafeComparator
。
示例(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 );
这将打印:
Foo{bar='null'}
Foo{bar='aaa'}
Foo{bar='zzz'}
答案 7 :(得分:1)
在我看来,没有一种方法可以做到,但无论如何代码不会那么长。
答案 8 :(得分:1)
你不应该像你那样使用NullComparator - 你正在为每个比较操作创建一个新的类实例,例如,你正在对包含1000个条目的列表进行排序,这将是1000 * log2(1000)对象,这些对象完全是多余的。这很快就会出现问题。
要么将其子类化,要么委托给它,或者只是实现自己的空检查 - 它实际上并不复杂:
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);
}
}
答案 9 :(得分:1)
将客户视为POJO。我的回答是:
Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId()));
或者
Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo));
答案 10 :(得分:0)
我认为早期的退货声明将是许多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.