【码农归外野】 java 高性能compareTo的实现

Tips:点击图片进入下一页

假设有一个java class 每个对象包含两个 bigdecimal类型 .

 现在想实现一个排序用的compareTo函数。有没有知道最佳写法是什么。

规则是if(A.x < B.x) return -1
          else if (A.x> B.x) return 1
                else if (A.y< B.y) return -1
                      else if (A.y > B.y) return 1
                             else return 0

我当然知道这么写性能很挫。有没有人知道怎么写性能更好。


网友评论:
    if (A.x > B.x || A.y > B.y) return 1;
    else if (A.x < B.x || A.y < B.y) return -1;
    else return 0;
复制代码
不要动不动就谈性能,你先代码写清楚。代码写清楚了,性能不会差到哪里去。
while… case 语法?

应该就这么写

如果只是排序的话,偏序不就够了吗
    if (A.x == B.x) {
            return A.y < B.y
    }
    return A.x < B.x;
复制代码
为啥要等于0的情况?
连这个的性能都需要去扣的场景,为什么还用java
如果没什么特别的,分开比较好,然后让编译器自己优化。。。

    if (A.x < B.x) return -1
        else if (A.x > B.x) return 1

    if (A.y < B.y) return -1
        else if (A.y > B.y) return 1

    return 0
复制代码



是这个理
我怎么感觉2楼写的是错的,这代码意思是优先比较x,如果x相同则比较y吧…

—— 来自 Xiaomi MI 6, Android 8.0.0上的 v2.1.0-play
试了几次以后现在是这么写的
if(A.x < B.x) return -1
  else if (A.x < B.x ) return 1
       else (return A.y.compareTo(B.y))

只是不知道这算不是best practice。
return (A.x.CompareTo(B.x)*2+ A.y.CompareTo(B.y)).CompareTo(0);

别这么写就行。

你这么写是不对的。
而且大部分时候用不到y,比较y的值会带来额外的性能损失

我们组用clojure不知道能不能支持多返回。
代码长不代表性能糟,直接写100条相同语句的性能比执行100遍的for循环还要高呢。
        if (A.x == B.x) {
                return A.y - B.y;
        }
        return A.x - B.x;
复制代码

这样就可以了。compareTo只要符号对就行了,又不是非要1和-1



看错了 编辑掉 好久没写java都忘了 应该是

var s=lhs.x.compareTo(rhs.x);
return s==0?lhs.y.compareTo(rhs.y):s;

应该是这意思吧

bigdecimal还好点,普通数字类型会有溢出问题的。所以jdk实现都是返回1,0和-1。
八楼正解。二楼的算法,如果A.x < B.x && A.y > B.y时会返回错误的结果。
这个时候你需要if(likely(cond))。

—— 来自 HUAWEI LYA-AL10, Android 9上的 v2.1.0-play

你这不对的啊
java  高性能
是不是有哪里不对

—— 来自 Sony G8342, Android 9上的 v2.1.2
用lambda可以吗?a.x.compareTo(b.x)==0? a.y.compareTo(b.y) : a.x.comparetob.x
牛批牛批  多一个比较的指令的性能都要扣。从业近十年没听说过这种场景,我孤陋寡闻了。

不过如果让我去做这种场景,我肯定不会选择java

—— 来自 Xiaomi MI 6, Android 8.0.0上的 v2.1.2

你的库给别人用,你也不知道场景是什么啊,当然能省则省
O(1)的性能也要扣,为什么不用C呢
if (A.x != B.x) {
  return A.x > B.x ? 1 : -1;
}

if (y再来一遍)
}

return 0;

应该是这样吧
这种不设计线程,不涉及io的代码,谈优化没意义
满足功能再美化下可读性就可以了


你是不是觉得gcc的-funroll-loop的作者是个丈育

你都用垃圾语言java了
还在乎什么性能啊

手动给likely点赞

java早就甩掉低性能的帽子了
各种层面的优化加上去,虽然跟(写的好)的C/C++比不了,但已经可以应用在很多性能敏感领域了
多少高级语言看着jvm的效率眼馋,想着搞一个jvm runtime
LZ为什么不使用标准库里的  java.math.BigDecimal.compareTo 呢?

int res = (A.x).compareTo(B.x);
if (res == 0) {....}

这样可以避免对两个 BigDecimal 进行重复的比较

ref
http://docs.oracle.com/javase/7 ... imal.html#compareTo(java.math.BigDecimal)
http://www.geeksforgeeks.org/bi ... o-function-in-java/

 我试一下。好行
不觉得java哪里低性能,c++的循环性能大约也就java的20倍这样,20倍的差距感觉不算啥。


不知道你们这些CPP巨魔在这里嚷嚷个啥。
你们写过BLAS吗。看过GOTO的论文吗?
有人能告诉我这个场景和CPP的强有一分钱关系吗?
来了 开始了 开始了
又到了我第二喜欢的世界上哪种编程语言最好的环节了
果然又回到了这个问题
来人,上FPGA!
_x = a.x.compare(b.x)
_y = a.y.compare(b.y)

return _x!=0? _x : _y

并发得飞起

php天下第一
这贴要是在爆栈上面发…
首先lz被标重复提问
然后二楼大概要被downvote到哭

不玩梗的话,听说php7.几吊锤nodejs了?

    public class YouClass implements Comparable{
        BigDecimal x;
        BigDecimal y;

        @Override
        public int compareTo(YouClass other) {
            int res = x.compareTo(other.x);
            return res == 0? y.compareTo(other.y): res;
        }
    }
复制代码或者这样





附赠BigDecimal 的 compareTo
    public int compareTo(BigDecimal val) {
        // Quick path for equal scale and non-inflated case.
        if (scale == val.scale) {
            long xs = intCompact;
            long ys = val.intCompact;
            if (xs != INFLATED && ys != INFLATED)
                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
        }
        int xsign = this.signum();
        int ysign = val.signum();
        if (xsign != ysign)
            return (xsign > ysign) ? 1 : -1;
        if (xsign == 0)
            return 0;
        int cmp = compareMagnitude(val);
        return (xsign > 0) ? cmp : -cmp;
    }
复制代码Comparator.thenComparing

一个比较指令要抠性能,就算是汇编也省不了多少,不如到别的地方看看能不能省个θ(n)出来

会溢出

为什么要上FPGA

treemap 插入comparator可以省nlogn