我正在为这样一个简单的类实现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
}

我希望这些对象的natural ordering是: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);
}

这就行了,但我对这段代码不太满意.诚然,它并不复杂,但相当冗长乏味.

问题是,how would you make this less verbose(同时保留功能)?如果Java标准库或Apache Commons有帮助,请随时参考.让这个(稍微)简单一点的唯一 Select 是实现我自己的"NullSafeStringComparator",并将其应用于比较这两个字段吗?

Edits 1-3:埃迪是对的;修正了上面的"两个名字都是空的"情况

关于公认的答案

我在2009年在Java1.6上问过这个问题,当时100是我首选的答案.直到现在(2017年),我才抽出时间来改变这一点.

还有3rd party library solutions个-2009年的Apache Commons Colltions One和2013年的Guava One,都是我发布的-在某个时候我确实更喜欢.

我现在把答案说清楚了.如果是在Java8上,这肯定是首选,现在Java8应该可以用于几乎所有的项目.

推荐答案

使用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);
}

Java相关问答推荐

LocalTime解析截断时间的第二个值

在Keycloak测试容器中的测试之间清理数据库

将@ManyToOne JPA Composite Key用作Id保存实体添加额外参数

Spring安全实现多个SQL表身份验证

如何审查Java dtos中的自定义注释字段?

如何将kotlin代码转换为java

多个Java线程和TreeMap.put()的非预期行为

Java函数式编程中的双值单值映射

放气总是压缩整个街区吗?

测试期间未执行开放重写方法

如何在Java记录中设置BigDecimal类型属性的精度?

WebSockets和Spring Boot安全性出现错误401

继续收到错误SQLJDBC EXCEPTION执行";org.springframework.dao.InvalidDataAccessResourceUsageException:&

虚拟线程应该很快消亡吗?

如何使用路径过渡方法使 node 绕圆旋转?

Regex以查找不包含捕获组的行

Oj算法 MatrixR032从字符串、归一化和余弦相似度计算创建

组合连接以从两个表返回数据

无限递归Java问题

原始和参数化之间的差异调用orElseGet时可选(供应商)