安卓怎么让程序一直运行 如何让你的程序运行的更快
如何让你的程序运行的更快

在总体的框架设计确定以后 多注意一些编程细节 积少成多 可以获得更佳的性能 让程序跑的更快! 前些天同事优化代码时提到了String和StringBuffer 仔细想想 发现自己也就是知道个大概 所以查了 一下资料 文章中有错误的地方你可一定要告诉我啊 呵呵^+^ 一 介绍 String:非可变类(immutable) 一旦创建就不能再被改变 StringBuffer:可变类 创建之后可以被改变 何谓非可变类? 简单说 非可变类的实例是不能被修改的 每个实例中包含的信息都必须在该实例创建的时候就提供出来 并且在对象的整个生存周期内固定不变 非可变类好处 状态单一 对象简单 便于维护 通常是线程安全的 用户可以共享非可变对象 甚至可 以共享它们的内部信息 二 创建字符串 两种方法 String s = hello ; String s = new String( hello ) 哪种方式性能更好? 例 : //create String without new keyword longstartTime =System currentTimeMillis() for(inti= ;i< ;i++){ String str = hello ; } longendTime =System currentTimeMillis() System out println( create String without new keyword : +(endTime startTime )+ milli seconds ) //create String with new keyword longstartTime =System currentTimeMillis() for(inti= ;i< ;i++){ String str = newString( hello ) } longendTime =System currentTimeMillis() System out println( create String with new keyword : +(endTime startTime )+ milli seconds ) 输出结果为(注 程序的输出结果也许和你的结果不同 但是总体趋势应该是一致的) create String without new keyword : milli seconds create String with new keyword : milli seconds 结论 创建字符串变量时尽可能不使用new关键字 说明 虽然两个语句都是返回一个String对象的引用 但是jvm对两者的处理方式是不一样的 对于第一种不用new关键字创建String对象 JVM首先会在内部维护的滞留字符串中通过String的equels方法查找是对象池中是否存放有该 String对象 如果有 返回已有的String对象给用户 而不会在heap中重新创建一个新的String对象 如 果对象池中没有该String对象 JVM则在heap中创建新的String对象 将其引用返回给用户 同时将该引 用添加至滞留字符串中 对于第二种使用new关键字创建String对象 JVM会马上在heap中创建一个String对象 然后将该对象的引用返回给用户 JVM是不会主动把该 对象放到滞留字符串里面的 除非程序调用 String的intern()方法 JVM为字符串自变量维护一些唯一的String对象 程序员不需要为字符串自变量而发愁 但是使用new关键 字可能会在内存中创建重复的String对象 你不必为此而烦恼 intern()方法可以帮你解决问题 String intern() 检查字符串对象的存在性 如果需要的字符串对象已经存在 那么它会将引用指向已 经存在的字符串对象而不是重新创建一个 例 : String str = world ; String str = newString( world ) if(str ==str ){ System out println( str == str ) } else{ System out println( str != str ) } //输出 str != str String str = world ; if(str ==str ){ System out println( str == str ) } else{ System out println( str != str ) } //输出 str == str str =str intern() if(str ==str ){ System out println( after intern() str == str ) } else{ System out println( after intern() str != str ) } //输出 after intern() str == str 结论 如果使用new关键字创建了字符串变量 则尽可能使用intern()方法 上面的例子执行正是用到了string对象的不可变性质 既然string对象一旦创建就不可以改变 那么多个 引用指向同一个对象就不会对彼此产生影响 三 字符串连接 你可以使用+操作符或者ncat()或者StringBuffer append()等办法来连接多个字符串 哪 一种方法性能最佳? 如何选择取决于两种情景 第一种情景 需要连接的字符串是在编译期间决定的 还是在运行期间决定 第二种情景 你使用的是 StringBuffer还是String 通常程序员会认为StringBuffer append()方法会优于+操作符或 ncat()方法 但是在一些特定 的情况下这个假想是不成立的 ) 第一种情景 编译期间决定VS运行期间决定 //test the string Concatenation longstartTime =System currentTimeMillis() for(intk= ; k< ; k++){ String str = this is + a test + for string concatenation ; } longendTime =System currentTimeMillis() System out println( string concatenation using + : +(endTime startTime )+ milli seconds ) longstartTime =System currentTimeMillis() for(intk= ; k< ; k++){ String str = this is ; ncat( a test ) ncat( for string concatenation ) } longendTime =System currentTimeMillis() System out println( string concatenation using concat() : +(endTime startTime )+ milli seconds ) longstartTime =System currentTimeMillis() for(intl= ; l< ; l++){ StringBuffer sb = newStringBuffer() sb append( this is ) sb append( a test ) sb append( for string concatenation ) } longendTime =System currentTimeMillis() System out println( string concatenation using append() : +(endTime startTime )+ milli seconds )
上面代码的输出结果 string concatenation using + : milli seconds string concatenation using concat() : milli seconds string concatenation using append() : milli seconds 很有趣 +操作符比StringBuffer append()方法要快 Why? 这是因为编译器对简单的字符串进行了优化 即使使用new关键字来创建String对象的时候也是如此 例 如 编译前 String str = this is + a test + for string concatenation ; 编译后 String str = this is a test for string concatenation ; 这里String对象在编译期间就决定了而StringBuffer对象是在运行期间决定的 运行期间决定需要额外的 开销 结论 如果字符串在编译期间就可以决定它的值 则字符串拼接的时候 + 操作符效率更高 简单的 认为append()效率高于 + 是错误的 ) 第二种情景 StringBufferVSString //string concatenation using += longstartTime =System currentTimeMillis() String str = hello ; for(inti= ; i< ; i++){ str += hello ; } longendTime =System currentTimeMillis() System out println( string concatenation using += : +(endTime startTime )+ milli seconds ) //string concatenation using append() longstartTime =System currentTimeMillis() StringBuffer sb = newStringBuffer( hello ) for(inti= ; i< ; i++){ sb append( hello ) } longendTime =System currentTimeMillis() System out println( string concatenation using append() : +(endTime startTime )+ milli seconds ) 上面代码的输出结果 string concatenation using += : milli seconds string concatenation using append() : milli seconds 结论 避免使用 += 来构造字符串 虽然两者都是在运行期间决定字符串对象 但是使用+=操作符会产生更多的临时对象 在上例中 由于String类是不可变的 所以进行字符串拼接的时候 每循环一次就会产生临时对象来保存 str 和 hello 的值 之后创建一个临时的StringBuffer对象 并调用其append()方法来完成字符串的 拼接 最后调用toString()方法 将临时StringBuffer对象转为String再赋值给str 此时str 已经改变 指向了新的对象 ) 第三种情景 设置StringBuffer的容量来提升性能 longstartTime =System currentTimeMillis() StringBuffer sb = newStringBuffer( hello ) for(inti= ; i< ; i++){ sb append( hello ) } longendTime =System currentTimeMillis() System out println( string concatenation using append() : +(endTime startTime )+ milli seconds ) //set the StringBuffer capacity longstartTime =System currentTimeMillis() StringBuffer sb = newStringBuffer( hello ) sb ensureCapacity( ) for(inti= ; i< ; i++){ sb append( hello ) } longendTime =System currentTimeMillis() System out println( string concatenation using append() after set the StringBuffer capacity : milli seconds ) 上面代码的输出结果 string concatenation using append() : milli seconds string concatenation using append() after set the StringBuffer capacity : milli seconds 结论 声明StringBuffer对象的时候 指定合适的capacity 会提升程序性能 )使用StringBuffer的构造函数来设定它的初始化容量 StringBuffer(int length) )使用ensureCapacity(int minimumcapacity)方法在StringBuffer对象创建之后设置它的容量 首先我们看看StringBuffer的缺省行为 然后再找出一条更好的提升性能的途径 StringBuffer的缺省行为 StringBuffer在内部维护一个字符数组 当你使用缺省的构造函数来创建StringBuffer对象的时候 StringBuffer的容量被初始化为 个字符 也就是说缺省容量就是 个字符 当StringBuffer达到最大容 量的时候 它会将自身容量增加到当前的 倍再加 也就是( *旧值+ ) 如果你使用缺省值 初始化之后接着往里面追加字符 在你追加到第 (原文是 其实是错误的 因为在追加到第 个字符的时候 容量不会发生变化 很抱歉 以后会更严谨一些^+^)个字符的时候它会将容量增加 到 ( * + ) 当追加到 个字符的时候就会将容量增加到 ( * + ) 无论何事只要StringBuffer 到达它的最大容量它就不得不创建一个新的字符数组然后重新将旧字符和新字符都拷贝一遍 所以给 StringBuffer设置一个合理的初始化容量值 会提升程序的性能 但是为什么容量变化的时候是 *旧值+ 呢?有谁能告诉我么?查资料的时候没有找到 附 查资料的过程中发现了jdk 还提供了StringBuilder类 我是没有用过 不过也介绍一下好了 Java lang StringBuffer 线程安全的可变字符序列 类似于 String 的字符串缓冲区 但不能修 改 可将字符串缓冲区安全地用于多个线程 可以在必要时对这些方法进行同步 因此任意特定实例上的 所有操作就好像是以串行顺序发生的 该顺序与所涉及的每个线程进行的方法调用顺序一致 每个字符串缓冲区都有一定的容量 只要字符串缓冲区所包含的字符序列的长度没有超出此容量 就无需分配新的内部缓冲区数组 如果内部缓冲区溢出 则此容量自动增大 从 JDK 开始 为该 类增添了一个单个线程使用的等价类 即 StringBuilder 与该类相比 通常应该优先使用 StringBuilder 类 因为它支持所有相同的操作 但由于它不执行同步 所以速度更快 但是如果将 StringBuilder 的实例用于多个线程是不安全的 需要这样的同步 则建议使用 StringBuffer lishixinzhi/Article/program/Java/hx/201311/26749