java compare null,如何简化一个null安全的compareTo()实现?

I'm implementing compareTo() method for a simple class such as this (to be able to use Collections.sort() and other goodies offered by the Java platform):

public class Metadata implements Comparable {

private String name;

private String value;

// Imagine basic constructor and accessors here

// Irrelevant parts omitted

}

I want the natural ordering for these objects to be: 1) sorted by name and 2) sorted by value if name is the same; both comparisons should be case-insensitive. For both fields null values are perfectly acceptable, so compareTo must not break in these cases.

The solution that springs to mind is along the lines of the following (I'm using "guard clauses" here while others might prefer a single return point, but that's beside the point):

// 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);

}

This does the job, but I'm not perfectly happy with this code. Admittedly it isn't very complex, but is quite verbose and tedious.

The question is, how would you make this less verbose (while retaining the functionality)? Feel free to refer to Java standard libraries or Apache Commons if they help. Would the only option to make this (a little) simpler be to implement my own "NullSafeStringComparator", and apply it for comparing both fields?

Edits 1-3: Eddie's right; fixed the "both names are null" case above

解决方案

I would implement a null safe comparator. There may be an implementation out there, but this is so straightforward to implement that I've always rolled my own.

Note: Your comparator above, if both names are null, won't even compare the value fields. I don't think this is what you want.

I would implement this with something like the following:

// 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);

}

EDIT: Fixed typos in code sample. That's what I get for not testing it first!

EDIT: Promoted nullSafeStringComparator to static.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CAS(Compare and Swap)队列是一种基于无锁的并发编程实现,其核心思想是利用原子操作的特性来实现线程安全的数据访问。下面是用Java实现一个简单的CAS队列的示例代码: ```java import java.util.concurrent.atomic.AtomicReference; public class CASQueue<T> { private AtomicReference<Node<T>> head; private AtomicReference<Node<T>> tail; public CASQueue() { Node<T> dummy = new Node<>(null); head = new AtomicReference<>(dummy); tail = new AtomicReference<>(dummy); } public void enqueue(T item) { Node<T> newNode = new Node<>(item); while (true) { Node<T> curTail = tail.get(); Node<T> tailNext = curTail.next.get(); if (curTail == tail.get()) { if (tailNext != null) { tail.compareAndSet(curTail, tailNext); } else { if (curTail.next.compareAndSet(null, newNode)) { tail.compareAndSet(curTail, newNode); return; } } } } } public T dequeue() { while (true) { Node<T> curHead = head.get(); Node<T> curTail = tail.get(); Node<T> headNext = curHead.next.get(); if (curHead == head.get()) { if (curHead == curTail) { if (headNext == null) { return null; } tail.compareAndSet(curTail, headNext); } else { T item = headNext.item; if (head.compareAndSet(curHead, headNext)) { return item; } } } } } private static class Node<T> { private T item; private AtomicReference<Node<T>> next; public Node(T item) { this.item = item; this.next = new AtomicReference<>(null); } } } ``` 这个队列中的每个节点都包含一个元素和一个指向下一个节点的引用。队列的头部和尾部都是用AtomicReference来保证线程安全。enqueue方法中,我们首先创建一个新的节点,然后利用CAS操作来将其添加到队列的尾部。如果队列的尾部发生了变化,我们需要再次尝试添加节点。dequeue方法中,我们利用CAS操作来将队列的头部指针向前移动,并返回移除的元素。如果队列为空,则返回null

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值