Guava 中的链接顺序

发布于 2024-10-17 03:16:54 字数 1875 浏览 8 评论 0原文

我对番石榴及其风格有点陌生。我确实在挖掘它,但我一直被绊倒的一件事是链式方法的顺序。我似乎遇到这个问题最多的是使用复合Ordering时。我必须不断问自己这样的问题:

  • 自然去哪儿了?
  • nullFirst(或最后一个)去哪里了?
  • 哪个 nullsFirst 做什么? (在下面的示例中,一个用于主机,一个用于姓氏,一个用于名字?)

这是我刚刚正在处理的一个示例。它看起来很麻烦,我只是不确定我是否把它们放在一起正确。我有一些 JUnit 来测试它,看起来还不错,但总是存在那些奇怪的边界情况。

Ordering<Host> lastNameThenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
    public String apply(Host host) {
        return host.getLastName();
    }}).compound(Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
    public String apply(Host host) {
        return host.getFirstName();
    }})).nullsFirst();

至于一个实际问题:这些事情如何执行是否有明确的规则?它似乎是从最后到第一个,但我很难说清楚。

编辑:只是想指出我试图替换的又大又丑的代码:

    Ordering<Host> ordering2 = new Ordering<Host>() {
        public int compare(Host host1, Host host2) {
            if (host1 == null || host2 == null) {
                return host1 == host2 ? 0 : ((host1 == null) ? -1 : 1); 
            }
            if(host1.getLastName() != null || host2.getLastName() != null){
                if (host1.getLastName() == null) {
                    return -1;
                } else if (host2.getLastName() == null) {
                    return 1;
                }

                if (host1.getLastName().compareTo(host2.getLastName()) != 0) {
                    return host1.getLastName().compareTo(host2.getLastName());
                }
            }

            if (host1.getFirstName() == null) {
                return -1;
            } else if (host2.getFirstName() == null) {
                return 1;
            }

            return host1.getFirstName().compareTo(host2.getFirstName());
        }};

I'm a bit new to Guava and it's style. I'm definitely digging it, but one thing I keep tripping over is the order of chained methods. Where I seem to have this problem the most is when using compound Orderings. I have to keep asking myself questions like:

  • Where does the natural go?
  • Where does the nullFirst (or last) go?
  • Which nullsFirst does what? (In the example below, one for host, one for last name, one for first name?)

Here's an example of one that I was just working on. It looks cumbersome, and I'm just not sure if I put it all together right. I have some JUnits to test it, and it seems okay, but there are always those quirky boundary cases.

Ordering<Host> lastNameThenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
    public String apply(Host host) {
        return host.getLastName();
    }}).compound(Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
    public String apply(Host host) {
        return host.getFirstName();
    }})).nullsFirst();

As for an actual question: Is there a well-defined rule for how these things get executed? It seems to be last-to-first, but I'm having trouble telling that.

edit: Just wanted to point out the large, ugly code I was trying to replace:

    Ordering<Host> ordering2 = new Ordering<Host>() {
        public int compare(Host host1, Host host2) {
            if (host1 == null || host2 == null) {
                return host1 == host2 ? 0 : ((host1 == null) ? -1 : 1); 
            }
            if(host1.getLastName() != null || host2.getLastName() != null){
                if (host1.getLastName() == null) {
                    return -1;
                } else if (host2.getLastName() == null) {
                    return 1;
                }

                if (host1.getLastName().compareTo(host2.getLastName()) != 0) {
                    return host1.getLastName().compareTo(host2.getLastName());
                }
            }

            if (host1.getFirstName() == null) {
                return -1;
            } else if (host2.getFirstName() == null) {
                return 1;
            }

            return host1.getFirstName().compareTo(host2.getFirstName());
        }};

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

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

发布评论

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

评论(3

2024-10-24 03:16:54

我认为你的做法是正确的,但非常丑陋。为了提高可读性,请尝试以下操作:

使用枚举

将函数移动到实现 Function 的枚举。每个枚举项都可以提供它自己的实现。

enum HostFunctions implements Function<Host, String>{
    GETFIRSTNAME{

        @Override
        public String apply(final Host host){
            return host.getFirstName();
        }
    },
    GETLASTNAME{

        @Override
        public String apply(final Host host){
            return host.getLastName();
        }
    }

}

缩进代码

现在引用这些枚举函数并正确缩进代码。这就是它的样子:

final Ordering<Host> orderingByLastAndFirstName =
    Ordering
        .natural()
        .nullsFirst()
        .onResultOf(HostFunctions.GETLASTNAME)
        .compound(
            Ordering
                .natural()
                .nullsFirst()
                .onResultOf(HostFunctions.GETFIRSTNAME))
        .nullsFirst();

我想说这会让一切变得更容易理解。

IDE 配置

关于正确的缩进(至少如果您使用 Eclipse),请参阅以下问题:

如何缩进流畅界面
使用 eclipse “正确地”构建模式?

枚举作为函数

关于枚举:这称为枚举单例模式。 Guava 的人在他们的代码库中都使用它。 在维基百科Effective Java,第 3 项。虽然这些来源都讨论单项枚举,但这里的方法几乎相同。

I think what you do is correct, but awfully ugly. Try this for readability:

Use an Enum

Move the functions to an enum that implements Function<Host, String>. Each of the enum items can provide it's own implementation.

enum HostFunctions implements Function<Host, String>{
    GETFIRSTNAME{

        @Override
        public String apply(final Host host){
            return host.getFirstName();
        }
    },
    GETLASTNAME{

        @Override
        public String apply(final Host host){
            return host.getLastName();
        }
    }

}

Indent your Code

Now reference those enum functions and indent your code properly. This is what it will look like:

final Ordering<Host> orderingByLastAndFirstName =
    Ordering
        .natural()
        .nullsFirst()
        .onResultOf(HostFunctions.GETLASTNAME)
        .compound(
            Ordering
                .natural()
                .nullsFirst()
                .onResultOf(HostFunctions.GETFIRSTNAME))
        .nullsFirst();

I'd say that makes everything much more understandable.

IDE Configuration

Regarding proper indentation (at least if you use Eclipse), see this question:

How to indent the fluent interface
pattern “correctly” with eclipse?

Enums as Functions

Regarding the enum: this is called the enum singleton pattern. The Guava guys use it all over their code base. Read about it on wikipedia or in Effective Java, Item 3. Although those sources both talk about single-item enums, the approach is almost the same here.

独夜无伴 2024-10-24 03:16:54

每个链接调用都会将先前的顺序“包装”到新的顺序中,所以你是对的,执行顺序可以被认为是“向后”的。

我编写并审阅了 Ordering 类,但我仍然经常不得不停下来,为 nullsFirst()、onResultOf() 和 reverse() 的正确交错摸不着头脑!

Each chaining call is "wrapping" the previous ordering into a new one, so you're right, the execution order can be thought of as "backwards".

I wrote and reviewed the Ordering class and I still regularly have to stop and scratch my head over the correct interleaving of nullsFirst(), and onResultOf() and reverse()!

鹿港小镇 2024-10-24 03:16:54

以下是我对此的偏好,假设您必须能够处理null主机、名字和姓氏。对我来说,似乎非 null 名字和姓氏应该是 Host 类的要求。通常,您应该尽量避免允许集合包含 null 对象。

Ordering<Host> lastNameFirstNameOrdering = new Ordering<Host>() {
  @Override public int compare(Host left, Host right) {
    return ComparisonChain.start()
      .compare(left.getLastName(), right.getLastName(), Ordering.natural().nullsFirst())
      .compare(left.getFirstName(), right.getFirstName(), Ordering.natural().nullsFirst())
      .result();
  }
}.nullsFirst();

或者,我会采取类似于 Sean 的方法,但为了可读性而将其分解。

Ordering<Host> lastNameOrder = Ordering.natural().nullsFirst()
    .onResultOf(Host.LAST_NAME);
Ordering<Host> firstNameOrder = Ordering.natural().nullsFirst()
    .onResultOf(Host.FIRST_NAME);
Ordering<Host> orderingByLastAndFirstName =
     lastNameOrder.compound(firstNameOrder).nullsFirst();

请记住,您还可以将这些单独的排序设置为类的静态最终字段,以便您在排序时可以在任何地方轻松使用它们,例如 Host.LAST_NAME_ORDER

The following would be my preference for doing this, assuming you must be able to handle null hosts, first names and last names. To me, it seems like a non-null first name and last name ought to be a requirement of the Host class. And you should generally try to avoid allowing collections to contain null objects.

Ordering<Host> lastNameFirstNameOrdering = new Ordering<Host>() {
  @Override public int compare(Host left, Host right) {
    return ComparisonChain.start()
      .compare(left.getLastName(), right.getLastName(), Ordering.natural().nullsFirst())
      .compare(left.getFirstName(), right.getFirstName(), Ordering.natural().nullsFirst())
      .result();
  }
}.nullsFirst();

Alternatively, I'd take an approach similar to Sean's but break things down for readability.

Ordering<Host> lastNameOrder = Ordering.natural().nullsFirst()
    .onResultOf(Host.LAST_NAME);
Ordering<Host> firstNameOrder = Ordering.natural().nullsFirst()
    .onResultOf(Host.FIRST_NAME);
Ordering<Host> orderingByLastAndFirstName =
     lastNameOrder.compound(firstNameOrder).nullsFirst();

Keep in mind that you could also make these individual orderings static final fields of the class, allowing you to easily use them anywhere when sorting like Host.LAST_NAME_ORDER.

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