1
@SuppressWarnings("unchecked")
public static final Ordering<EmailTemplate> ARBITRARY_ORDERING = (Ordering)Ordering.arbitrary();

public static final Ordering<EmailTemplate> ORDER_BY_NAME = Ordering.natural().nullsFirst().onResultOf(GET_NAME);

public static final Ordering<EmailTemplate> ORDER_BY_NAME_SAFE = Ordering.allEqual().nullsFirst()
            .compound(ORDER_BY_NAME)
            .compound(ARBITRARY_ORDERING);

这是用于订购 EmailTemplate 的代码。如果我有一个 EmailTemplate 列表,我希望列表的 null 元素出现在开头,然后是具有 null 名称的元素,然后按自然名称顺序,如果它们具有相同的名称,则任意顺序。


这是我应该做的吗?我认为通过“allEqual”启动比较器似乎很奇怪......

我还想知道处理 Ordering.arbitrary() 的最佳方法是什么,因为它是返回 Ordering 的静态方法。有什么优雅的使用方式吗?我不太喜欢这种无用的,带有警告的行:

@SuppressWarnings("unchecked")
public static final Ordering<EmailTemplate> ARBITRARY_ORDERING = (Ordering)Ordering.arbitrary();

顺便说一句,文档说:

返回对所有对象的任意排序,这compare(a, b) == 0意味着a == b(身份相等)。强加的命令没有任何意义,但它在 VM 的生命周期内是不变的。

这是否意味着与此 Ordering 进行比较的对象永远不会被垃圾收集?

4

2 回答 2

4

关于第二个问题:没有。Guava 使用对象的身份哈希码对它们进行任意排序。

关于第一个问题:我会使用比较链按名称排序,然后按任意顺序:

private class ByNameThenArbitrary implements Comparator<EmailTemplate> {
    @Override
    public int compare(EmailTemplate e1, EmailTemplate e2) {
        return ComparisonChain.start()
                              .compare(e1.getName(), e2.getName(), Ordering.natural().nullsFirst(),
                              .compare(e1, e2, Ordering.arbitrary())
                              .result();
    }
}

然后我会创建真正的排序,首先对带有空值的模板进行排序:

private static final Ordering<EmailTemplate> ORDER = 
    Ordering.fromComparator(new ByNameThenArbitrary()).nullsFirst();

不过没有测试。

于 2012-09-07T10:50:17.747 回答
3

我很确定,你做的太复杂了:

  • Ordering.arbitrary()适用于任何Object并且compound不需要将其限制为EmailTemplate
  • 比较时说nullsFirst()优先null,我建议最后应用它
  • 您不需要定义多个常量,这一切都应该很容易

我会去

public static final Ordering<EmailTemplate> ORDER_BY_NAME_SAFE = Ordering
    .natural()
    .onResultOf(GET_NAME)
    .compound(Ordering.arbitrary())
    .nullsFirst();

但我没有测试过。


这里令人困惑的是如何compoundnullsFirst工作的方式。前者this优先,后者测试null获胜。两者都是合乎逻辑的:

  • compound从左到右工作
  • nullsFirst必须首先测试 null,否则我们会得到一个期望

但综合起来很混乱。


这是否意味着与此 Ordering 进行比较的对象永远不会被垃圾收集?

不,它使用弱引用。只要一个对象没有在其他地方引用,它就可以被垃圾回收。这与“顺序在 VM 的生命周期内保持不变”并不矛盾,因为不再存在的对象无法再进行比较。

请注意,这Ordering.arbitrary()确实是任意的,并且基于对象的身份而不是 on equals,这意味着

 Ordering.arbitrary().compare(new String("a"), new String("a"))

不返回 0。

我想知道是否可以实现“等于兼容的任意排序”。

于 2012-09-07T10:49:37.560 回答