java long对比(java long bigdecimal)

生活百科 2023-04-30 10:17生活百科www.xingbingw.cn

java long对比(java long bigdecimal),本文通过数据整理汇集了java long对比(java long bigdecimal)相关信息,下面一起看看。

《Spring Boot 2 精髓》

2.1构造字符串String在Java中是不可变的。不管是构造的还是截取的,总会获得一个新的字符串。看看构造字符串源代码。

私有最终字符值[];公共字符串(String original){ this . value=original . value;this . hash=original . hash;}原字符串的值数组通过引用直接赋给新的字符串值,即两个字符串共用一个char数组,所以这种构造方法构造速度最快。Java中的字符串对象被设计成不可变的。意思是程序一旦得到一个字符串对象引用,就不用担心这个字符串在别处被修改了。不变性意味着线程安全,这将在第3章中解释。

在构造字符串比较频繁的时候,字符串是用字符串数组构造的,或者在一些帧的反序列化中,用byte[]构造字符串。在这种情况下,性能会很低。下面是通过char[]数组构造一个新的字符串源代码。

public String(char value[]){ this . value=arrays . copy of(value,value . length);}Arrays.copyOf将复制一个新数组,如下所示

public static char[]copy of(char[]original,int new length){ char[]copy=new char[new length];System.arraycopy(original,0,copy,0,Math.min(original.length,new length));返回副本;}你可以看到,通过数组构造一个字符串,实际上是创建了一个新的字符串数组。如果不是,或者直接引用char数组,那么如果从外部改变char数组,新的字符串也会改变。

char[] cs=new char[]{'a ',' b ' };String str=新字符串(cs);cs[0]='!'上面代码的一行修改了cs数组,不会影响str。因为str实际上是一个新的字符串数组。

通过char数组构造一个新的字符串是最长的方法。后面我们会看到,几乎每个string API都会调用这个方法来构造一个新的字符串,比如subString、concat等方法。下面的代码验证从字符串构造新字符串和使用char数组构造字符串的性能比较。

String str='你好,String ';char[]chars=str . tochararray();[@ Benchmark](0.4379833669001636 http 0.9730125339287456s 0.4379833669001636://0.973012539287456 my . oschina . net/u/3268003)public String String(){ return new String(str);}[@ Benchmark](0.4379833669001636 http 0.9730125339287456s 0.4379833669001636://0.9730125339287456 my . oschina . net/u/3268003)公共字符串stringByCharArray(){返回新字符串(chars);}输出是按照ns/op输出的,不仅是每次调用的纳秒数,还有char构造字符串的耗时,尤其是数组特别长的时候。

基准模式分数单位c . I . c . c . c .新字符串测试。字符串avgt 4.235ns/op c.i.c .新字符串测试stringbychararay avgt 11.704 ns/op按字节构造字符串,这是很常见的情况,尤其是现在分布式和微服务流行。字符串在客户端被序列化为字节数组并发送到服务器。服务器将有一个反序列化来通过字节构造字符串。

使用byte构造字符串来测试下面的性能测试。

Byte[] bs='你好,字符串'。getBytes(' UTF-8 ');[@ Benchmark](0.4379833669001636 http 0.9730125339287456s://my . oschina . net/u/3268003)公共字符串stringByByteArray()抛出异常{返回新字符串(bs,' UTF-8 ');}测试结果表明,byte构造一个字符串的时间太长,尤其是当要构造的字符串很长时。

基准模式评分单位c . I . c . c . newstringtest . string avgt 4.649 ns/op c . I . c . c . newstringtest . stringbytyearray avgt 82.166 ns/op . I . c . c . newstringtest . stringbycharray avgt 12.138 ns/op通过字节数组构造字符串,主要涉及转码过程,内部调用StringCoding.decode

this . value=string coding . decode(charset name,bytes,offset,length);CharsetName表示字符集,bytes表示字节数组,offset和length表示字节数组。

实际上,Charset子类负责代码转换。比如sun.nio.cs.UTF_8的decode方法负责字节转码。如果你深入这个类,你会发现你看到的是冰的一角,是冰下相当耗费CPU的转码工作,属于无法优化的部分。

在多次系统性能优化过程中,我发现字节数据组构造的字符串总是排在CPU消耗的最前面,转码消耗的系统性能抵得上几百行业务代码。所以我们的系统是分布式设计的,需要仔细设计要传输的字段,尽量避免使用String。例如,时间可以表示为long类型,业务状态也可以表示为int类型。下列对象需要序列化

类订单响应{//订单日期,格式' yyyy-mm-DD '私有字符串创建日期;//订单状态,' 0 '表示正常私有字符串状态;}可以改进为更好的定义,以减轻序列化和反序列化的负担。

class order response {//order date private long createDate;//订单状态,0表示正常private int状态;}关于微服务中传输对象的序列化和反序列化,第四章和第五章会介绍对象的序列化。

2.2字符串拼接JDK会自动转换用No到StringBuilder中,代码如下

String a=' helloString b=' world ' String str=a b虚拟机被编译成以下代码

String str=new StringBuilder()。追加(a)。追加(b)。toString();如果您运行JMH来测试这两段代码,性能实际上是相同的,因为使用连接字符串是一个常见的操作。虚拟机会对以上两段代码做一些优化,通过虚拟使用-XX: OptimizeStringConcat(默认开启)开启字符串拼接优化。如果采用下面的代码,虽然看起来和上面的代码片段很像,虚拟机无法识别这种字符串拼接模式,性能会下降很多。

StringBuilder sb=new StringBuilder();某人追加(a);某人追加(b);使用以下代码运行StringConcatTest类

String a='select u.id,u . name from user u ';字符串b=' where u.id=?';[@ Benchmark](0.4379833669001636 http 0.9730125339287456s 0.4379833669001636://0.9730125339287456 my . oschina . net/u/3268003)public String concat(){ String c=a b;返回c;}[@ Benchmark](0.4379833669001636 http 0.9730125339287456s 0.4379833669001636://0.9730125339287456 my . oschina . net/u/3268003)公共字符串concatbyOptimizeBuilder(){ String c=new StringBuilder()。追加(a)。追加(b)。toString();返回c;} @ Benchmark public string ConcatByBuilder(){//不会优化StringBuilder SB=New StringBuilder();某人追加(a);某人追加(b);return sb . tostring();}以下结果表明虚拟机优化发挥了作用。

基准模式分数单位c . I . c . c . stringconcate . concat avgt 25.747 ns/op c . I . c . c . stringconcate . concatbybuilder avgt 90.548 ns/op . I . c . c . stringconcate .ConcatByOptimizeBuilder AVGT 21.904 ns/OP你可以看到concatbyBuilder是最慢的,因为它没有经过JVM的优化。

这里的JVM优化指的是虚拟机的JIT优化,我们将在第8章解释。

读者可以自行验证一个b c的串拼接性能,看看是否优化过。

与StringBuilder类似,StringBuffer的主要函数继承自AbstractStringBuilder,使用synchronized关键字提供线程安全的方法,如append方法。

@ override public synchronized string buffer append(string str){//忽略其他代码super . append(str);还这个;}几乎所有的场景字符串拼接都不涉及线程同步,所以很少使用StringBuffer。上面的字符串拼接示例使用了StringBuffer,

@Benchmark公共字符串concatbyBuffer(){ String buffer sb=new String buffer();某人追加(a);某人追加(b);return sb . tostring();}输出如下所示

基准模式分数单位c。国际商会字符串证明。ConcatByBuffer AVGT 111.417 ns/OPC。国际商会字符串证明。ConcatByBuilder AVGT 94.758NS/OP可以看出,与StringBuffer相比,字符串拼接的性能还算不错,这得益于虚拟机的‘转义分析’,即JIT可能会在转义分析开启并消除锁的情况下消除这个对象上的同步锁。

转义分析-XX: DoEscapeAnalysis和锁消除-XX:精英锁,详见本书第八章JIT优化。

下面是一个锁消除的例子。对象obj只在方法内部使用,所以它可以消除synchronized。

Void foo() {//创建一个对象Object obj=new Object();synchronized(obj){ do something();}}}程序不应该依赖JIT优化。尽管转义分析和锁消除都已打开,但并不能保证所有代码都会得到优化,因为锁消除是在JIT的C2阶段进行优化的。作为一个程序员,应该不顾线程安全使用StringBuilder。

如果用StringBuilder拼接其他类型,尤其是数值类型,性能会明显下降。这是因为数字类型到字符的转换是在JDK内部进行的,需要做大量的工作。完成一个简单的Int类型到string的转换至少需要50行代码。我们在第一章已经看到了,这里就不详细解释了。当使用StringBuilder拼接字符串和数字时,需要考虑是否需要这样的字符串。

2.10 BigDecimal我们都知道浮点变量在计算时会失去精度。下面的代码

system . out . println(0.05 0.01);system . out . println(1.0-0.42);产量0.0600000001

可见,在Java中进行浮点运算时,会出现精度损失的问题。那么如果我们计算商品价格,就会出现问题。很可能我们手里有0.06元,却买不到一个0.05元和0.01元的商品。因为如上图,两者之和是0.0600000000000。这无疑是一个非常严重的问题,尤其是当电子商务网站的并发量上去的时候,问题将是巨大的。这可能会导致无法下订单,或对账出现问题。

通常有两种方法可以解决这个问题,如果账户余额可以表示为一个long来划分单元是最高效的。如果没有,就只能用BigDecimal类来解决这类问题。

BigDecimal a=new BigDecimal(' 0.05 ');BigDecimal b=new BigDecimal(' 0.01 ');BigDecimal ret=a . add(b);system . out . println(ret . tostring());只有用字符串构造BigDecimal才能不损失精度。如果使用new BigDecimal(0.05),构造的BigDecimal的精度会因为0.05本身的损失而损失。

BigDecimal可以保证精度,计算会有一定的性能影响。下面是测试平衡计算,用long表示分数,用BigDecimal表示元素的性能比较。

BigDecimal a=new BigDecimal(' 0.05 ');BigDecimal b=new BigDecimal(' 0.01 ');长c=5;长d=1;@ Benchmark @ compiler control(compiler control。mode . DONT _ INLINE)public long addByLong(){ return(c d);}@Benchmark@CompilerControl(编译器控制。mode . DONT _ INLINE)public BigDecimal addByBigDecimal(){ return a . add(b);}在我的机行里,上面的代码都能算准。通过JMH,测试结果如下

基准模式分数单位c.i.c.c. Bigdecimal测试。AddbyBigdecimal avgt 8.373 ns/op c . I . c . c . c . Bigdecimal测试。Addbylong avgt 2.984NS/op所以在项目中,如果涉及到精度结算,不使用double,可以考虑使用BigDecmal或者long来完成精度计算,这两种都有不错的性能,分布式或者微服务场景。考虑到序列化和反序列化,long也可以被所有序列化框架识别。

请参阅0.4379833669001636 http 0.9732532877 456s://0.9747456 www . jinshu . com。3667.86666565667

更多java long对比(java long bigdecimal)相关信息请关注本站,本文仅仅做为展示!

Copyright@2015-2025 www.xingbingw.cn 性病网版板所有