当前位置: 首页 > 面试题库 >

如何简化一个空安全的compareTo()实现?

诸彬郁
2023-03-14
问题内容

我正在compareTo()为这样的简单类实现方法(以便能够使用Collections.sort()和Java平台提供的其他功能):

public class Metadata implements Comparable<Metadata> {
    private String name;
    private String value;

// Imagine basic constructor and accessors here
// Irrelevant parts omitted
}

我希望这些对象的 自然排序
是:1)按名称排序,以及2)如果名称相同,则按值排序;两种比较均应不区分大小写。对于这两个字段,空值都是完全可以接受的,因此compareTo在这些情况下不得中断。

我想到的解决方案是遵循以下思路的(我在这里使用的是“保护条款”,而其他人可能更喜欢单个返回点,但那一点并不重要):

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(Metadata other) {
    if (this.name == null && other.name != null){
        return -1;
    }
    else if (this.name != null && other.name == null){
        return 1;
    }
    else if (this.name != null && other.name != null) {
        int result = this.name.compareToIgnoreCase(other.name);
        if (result != 0){
            return result;
        }
    }

    if (this.value == null) {
        return other.value == null ? 0 : -1;
    }
    if (other.value == null){
        return 1;
    }

    return this.value.compareToIgnoreCase(other.value);
}

这可以完成工作,但是我对这段代码并不完全满意。诚然,它不是 复杂,但是非常冗长乏味。

问题是, 如何使它变得不太冗长 (同时保留功能)?如果有帮助,请随时参考Java标准库或Apache
Commons。使这个(稍微)简单一点的唯一选择是实现自己的“ NullSafeStringComparator”并将其应用于比较两个字段吗?

编辑1-3 :埃迪的权利;修复了上面的“名字都为空”的情况

关于已接受的答案

我早在2009年就在Java 1.6上问了这个问题,当时我首选的
[是Eddie的纯JDK解决方案]

我将实现一个空安全比较器。可能有一个实现,但是实现起来如此简单,以至于我总是自己动手做。

注意:如果两个名称都为空,则上面的比较器甚至不会比较值字段。我认为这不是您想要的。

我将通过以下类似的方式实现此目的:

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(final Metadata other) {

    if (other == null) {
        throw new NullPointerException();
    }

    int result = nullSafeStringComparator(this.name, other.name);
    if (result != 0) {
        return result;
    }

    return nullSafeStringComparator(this.value, other.value);
}

public static int nullSafeStringComparator(final String one, final String two) {
    if (one == null ^ two == null) {
        return (one == null) ? -1 : 1;
    }

    if (one == null && two == null) {
        return 0;
    }

    return one.compareToIgnoreCase(two);
}

编辑:修复了代码示例中的错别字。这就是我不先测试就得到的!

编辑:将nullSafeStringComparator提升为静态。

。直到现在(2017年),我再也没有回过头来改变它。

现在,我将 Lukasz Wiktor 的干净了公认的答案。如果在Java
8上,那绝对应该是首选,现在,Java 8应该可以用于几乎所有项目。


问题答案:

使用 Java 8

private static Comparator<String> nullSafeStringComparator = Comparator
        .nullsFirst(String::compareToIgnoreCase);

private static Comparator<Metadata> metadataComparator = Comparator
        .comparing(Metadata::getName, nullSafeStringComparator)
        .thenComparing(Metadata::getValue, nullSafeStringComparator);

public int compareTo(Metadata that) {
    return metadataComparator.compare(this, that);
}


 类似资料:
  • 本文向大家介绍如何简单的实现一个promise?相关面试题,主要包含被问及如何简单的实现一个promise?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 首先明确什么是promiseA+规范,参考规范的地址:primise A+规范 如何实现一个promise,参考我的文章: 实现一个完美符合Promise/A+规范的Promise 一般不会问的很详细,只要能写出上述文章中的v1.0版本

  • 问题内容: 在Mysql中,有一个比较运算符,该运算符为null安全:<=>。创建如下这样的准备好的语句时,我在Java程序中使用了它: 现在,我想切换到H2数据库。如何在纯SQL中编写<=>运算符(例如使用IS NULL和IS NOT NULL)?我只想使用stmt.setString操作 一次 。可以多次写入列名。 参考:http : //dev.mysql.com/doc/refman/5.

  • 问题内容: 在Mysql中,有一个比较运算符,该运算符是null安全的:<=>。创建如下这样的准备好的语句时,我在Java程序中使用了它: 现在,我想切换到H2数据库。如何在纯SQL中编写<=>运算符(例如使用IS NULL和IS NOT NULL)?我只想使用stmt.setString操作 一次 。可以多次写入列名。 相关问题是在SQL中获取null == null。但是该答案要求将搜索值写入

  • 问题内容: 我使用JAXB创建XML消息。我需要创建的XML是(为简单起见): 我的代码如下所示: 问题:该元素未显示(标题为)。将header设置为空字符串时,将显示以下内容: 当我使用type 代替时,结果甚至更糟: 顺便说一句:我正在使用此代码来创建XML字符串。 是否可以获取空标签? 问题答案: 在XML中,并且是同一个东西。如果您真的想要前者,请使用修饰词。可能会为您做到这一点。

  • 本文向大家介绍如何实现一个全屏的功能?相关面试题,主要包含被问及如何实现一个全屏的功能?时的应答技巧和注意事项,需要的朋友参考一下 chrome下: 生产环境: 不同浏览器的实现方案不同,没有形成统一的标准。可以交由专门的类库———— screenFull实现。

  • 问题内容: 我是spring-security(Java)的新手,我正在寻找以下示例的简单示例: 如何使用Spring Security进行登录和注销 确保会话存在于每个页面上,如果没有,则再次重定向到登录名 如何获得对当前用户会话的访问权限 我的项目目前正在使用Spring MVC,并处于hibernate状态。 我已经构建了loginAPI + loginDAO,现在我需要结合安全性并确保某些