为什么我的简单比较器坏了?

发布于 2024-07-15 00:58:42 字数 661 浏览 6 评论 0原文

我有一个类,我已将其简化为:

final class Thing {
    private final int value;
    public Thing(int value) {
        this.value = value;
    }
    public int getValue() {
        return value;
    }
    @Override public String toString() {
        return Integer.toString(value);
    }
}

我想对这个东西的数组进行排序。 因此,我创建了一个简单的 copmarator:

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
        return a.getValue() - b.getValue();
    }
};

然后使用 Arrays.sort 的两个参数形式。

这对于我的测试用例来说效果很好,但有时会出现问题,数组以奇怪但可重复的顺序结束。 怎么会这样?

I have a class, which I have simplified to this:

final class Thing {
    private final int value;
    public Thing(int value) {
        this.value = value;
    }
    public int getValue() {
        return value;
    }
    @Override public String toString() {
        return Integer.toString(value);
    }
}

I want to sort an array of this thing. So I have created a simple copmarator:

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
        return a.getValue() - b.getValue();
    }
};

I then use the two argument form of Arrays.sort.

This works fine for my test cases, but sometimes it goes all wrong with the array ending up in a strange but repeatable order.
How can this be?

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

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

发布评论

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

评论(6

喵星人汪星人 2024-07-22 00:58:43

你在那里输入什么样的数字? 如果您的数字足够大,您可能会遍历整数的 MIN/MAX 值并最终陷入混乱。

What kind of numbers do you throw in there? If your numbers are large enough, you could wrap through the MIN/MAX values for integers and end up in a mess.

小清晰的声音 2024-07-22 00:58:43

如果a的值非常负并且b的值非常正,那么你的答案将是非常错误的。

IIRC,Int 溢出在 JVM 中悄无声息地缠绕

——MarkusQ

If a's value is very negative and b's value is very positive your answer will be very wrong.

IIRC, Int overflow silently wraps around in the JVM

-- MarkusQ

请持续率性 2024-07-22 00:58:43

try

System.out.println(Integer.MAX_Value - Integer.MIN_VALUE);

这需要返回一个正数,因为 MAX_VALUE > MIN_VALUE 但打印 -1

try

System.out.println(Integer.MAX_Value - Integer.MIN_VALUE);

This needs to return a positive number as MAX_VALUE > MIN_VALUE but instead prints -1

年少掌心 2024-07-22 00:58:43

比较 Java 基元时,建议将它们转换为对应的对象并依赖其 compareTo() 方法。

在这种情况下,您可以这样做:

return Integer.valueOf(a.getValue()).compareTo(b.getValue())

如有疑问,请使用经过良好测试的库。

When comparing Java primitives, it is advisable to convert them to their Object counterparts and rely on their compareTo() methods.

In this case you can do:

return Integer.valueOf(a.getValue()).compareTo(b.getValue())

When in doubt, use a well-tested library.

感受沵的脚步 2024-07-22 00:58:42

您不能使用减号来创建比较。 当绝对差值超过 Integer.MAX_VALUE 时,就会溢出。

相反,请使用此算法:

int compareInts( int x, int y ) {
  if ( x < y ) return -1;
  if ( x > y ) return 1;
  return 0;
}

我喜欢在库中将此函数用于此类目的。

You cannot use minus to create the comparison. You'll overflow when the absolute difference exceeds Integer.MAX_VALUE.

Instead, use this algorithm:

int compareInts( int x, int y ) {
  if ( x < y ) return -1;
  if ( x > y ) return 1;
  return 0;
}

I like to have this function in a library for such purposes.

丘比特射中我 2024-07-22 00:58:42

整数溢出……或更准确地说,下溢。

相反,进行显式比较:

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
      int av = a.getValue(), bv = b.getValue();
      return (av == bv) ? 0 : ((av < bv) ? -1 : +1);
    }
};

如果您确定差异不会“环绕”,则可以使用减法。 例如,当所讨论的值被限制为非负时。

Integer overflow… or more precisely, underflow.

Instead, do an explicit comparison:

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
      int av = a.getValue(), bv = b.getValue();
      return (av == bv) ? 0 : ((av < bv) ? -1 : +1);
    }
};

Using subtraction is fine if you are sure that the difference won't "wrap around". For example, when the values in question are constrained to be non-negative.

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