假设有一个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 runtimeLZ为什么不使用标准库里的 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;
}一个比较指令要抠性能,就算是汇编也省不了多少,不如到别的地方看看能不能省个θ(n)出来
会溢出
为什么要上FPGA
treemap 插入comparator可以省nlogn