比较()中的空字段该怎么办?

发布于 2024-07-06 05:38:25 字数 562 浏览 5 评论 0 原文

在 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
        }
    }

是否有一个标准的方法来处理o1o2o1.bar中的任何一个o2.bar 可以为 null,无需编写大量嵌套的 if...else

干杯!

In Java, I use a class in which some fields can be null. For example:

class Foo {
    String bar;
    //....
}

I want to write a BarComparator for this class,

    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?

Cheers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

生死何惧 2024-07-13 05:38:26

将客户视为 POJO。我的答案是:

Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId()));

或者

Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo));

Considering Customer as a POJO.My answer would be :

Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId()));

Or

Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo));
雨落□心尘 2024-07-13 05:38:26

我认为早期的 return 语句将是许多 if 的另一种选择

,例如

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.

I think early return statements would be the other alternative to lots of 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.
豆芽 2024-07-13 05:38:26

您不应该按照您的方式使用 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);
    }
}

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.

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);
    }
}
月寒剑心 2024-07-13 05:38:26

您还可以使用 Spring 框架中的 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'}

There is also the class org.springframework.util.comparator.NullSafeComparator in the Spring Framework you can use.

Example (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'}
不羁少年 2024-07-13 05:38:26

您可以为其编写比较器。 假设您有一个 Person 类,其 String 名称作为私有字段。 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));

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.

    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.

// 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));
猫性小仙女 2024-07-13 05:38:26

如果您使用的是 Google 集合,则可能会找到 比较器类很有帮助。 If 具有用于将 null 排序为集合中最大或最小元素的辅助方法。 您可以使用 复合比较器有助于减少代码量。

If you're using Google collections, you may find the Comparators class helpful. If has helper methods for ordering nulls as either the greatest or least elements in the collection. You can use compound comparators to help reduce the amount of code.

千紇 2024-07-13 05:38:26

这里的关键是弄清楚您希望如何处理空值。 一些选项是: a) 假设 null 值按排序顺序出现在所有其他对象之前 b) 假设 null 值按排序顺序出现在所有其他对象之后 c) 将 null 视为相当于某个默认值 d) 将 null 视为错误条件。 您选择哪一个完全取决于您正在处理的应用程序。

当然,在最后一种情况下,您会抛出异常。 对于其他情况,您需要一个四路 if/else 情况(大约三分钟的编码时间,您就已经弄清楚了您想要的结果)。

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.

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).

意中人 2024-07-13 05:38:26

这取决于您是否认为空条目是值得比较的有效字符串值。 为空 < 或> “苹果”。 我唯一可以肯定的是 null == null。 如果您可以定义 null 适合排序的位置,那么您可以适当地编写代码。

在这种情况下,我可能会选择抛出 NullPointerExcpetion 或 IllegalArgumentException,并尝试通过不首先将其放入比较中来在更高级别上处理 null。

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.

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.

滿滿的愛 2024-07-13 05:38:26

我想您可以使用一个小的静态方法来包装对字段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);
}

I guess you could wrap the call to the field compareTo method with a small static method to sort nulls high or low:

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);
}
洛阳烟雨空心柳 2024-07-13 05:38:26

感谢您的回复! 通用方法和谷歌比较器看起来很有趣。

我发现有一个 NullComparatorApache 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 字段,以保持重点。

Thanks for the replies! The generic method and the Google Comparators look interesting.

And I found that there's a NullComparator in the Apache Commons Collections (which we're currently using):

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文