String 使用的优化建议

其他 String 使用的优化建议

以上我们描述了在我们的大量文本分析案例中调用 String 的 subString方法导致内存消耗的问题,下面再列举一些其他将导致内存浪费的 String 的 API 的使用:

String 拼接的方法选择

在拼接静态字符串时,尽量用 +,因为通常编译器会对此做优化,如:

 String test = "this " + "is " + "a " + "test " + "string"

编译器会把它视为:

 String test = "this is a test string"

在拼接动态字符串时,尽量用 StringBuffer 或 StringBuilder的 append,这样可以减少构造过多的临时 String 对象。

String 构造的方法选择

常见的创建一个 String 可以用赋值操作符"=" 或用 new 和相应的构造函数。初学者一定会想这两种有何区别,举例如下:

 String a1 = “Hello”;
String a2 = new String(“Hello”);

第一种方法创建字符串时 JVM 会查看内部的缓存池是否已有相同的字符串存在:如果有,则不再使用构造函数构造一个新的字符串,直接返回已有的字符串实例;若不存在,则分配新的内存给新创建的字符串。

第二种方法直接调用构造函数来创建字符串,如果所创建的字符串在字符串缓存池中不存在则调用构造函数创建全新的字符串,如果所创建的字符串在字符串缓存池中已有则再拷贝一份到 Java 堆中。

尽管这是一个简单明显的例子,然而在实际项目中编程者却不那么容易洞察因为这两种方式的选择而带来的性能问题。

使用构造函数 string() 带来的内存性能隐患和缓解

仍然以之前的从 csv 文件中截取 String 为例,先前我们通过用 new String() 去除返回的 String 中附带的原始 String 的方法优化了 subString导致的内存消耗问题。然而,当我们下意识地使用 newString去构造一个全新的字符串而不是用赋值符来创建(重用)一个字符串时,就导致了另一个潜在的性能问题,即:重复创建大量相同的字符串。说到这里,您也许会想到使用缓存池的技术来解决这一问题,大概有如下两种方法:

方法一,使用 String 的 intern()方法返回 JVM 对字符串缓存池里相应已存在的字符串引用,从而解决内存性能问题,但这个方法并不推荐!原因在于:首先,intern() 所使用的池会是 JVM 中一个全局的池,很多情况下我们的程序并不需要如此大作用域的缓存;其次,intern() 所使用的是 JVM heap 中 PermGen 相应的区域,在 JVM 中 PermGen 是用来存放装载类和创建类实例时用到的元数据。程序运行时所使用的内存绝大部分存放在 JVM heap 的其他区域,过多得使用 intern()将导致 PermGen 过度增长而最后返回 OutOfMemoryError,因为垃圾收集器不会对被缓存的 String 做垃圾回收。所以我们建议使用第二种方式。

方法二,用户自己构建缓存,这种方式的优点是更加灵活。创建 HashMap,将需缓存的 String 作为 key 和 value 存放入 HashMap。假设我们准备创建的字符串为 key,将 Map cacheMap 作为缓冲池,那么返回 key 的代码如下:

 private String getCacheWord(String key) {
String tmp = cacheMap.get(key);
if(tmp != null) {
return tmp;
} else {
cacheMap.put(key, key);
return key;
}
}
 

回页首

结束语

本文通过一个实际项目中遇到的因使用 String 而导致的性能问题讲述了 String 在 JVM 中的存储结构,String 的 API 使用可能造成的性能问题以及解决方法。相信这些建议能对处理大文本分析的朋友有所帮助,同时希望文中提到的某些优化方法能被举一反三的应用在其他有关 String 的性能优化的场合。

String性能优化的更多相关文章

  1. Java 性能优化之 String 篇

    原文:http://www.ibm.com/developerworks/cn/java/j-lo-optmizestring/ Java 性能优化之 String 篇 String 方法用于文本分析 ...

  2. Java性能优化之String字符串优化

    字符串是软件开发中最重要的对象之一.通常,字符串对象在内存中是占据了最大的空间块,因此如何高效地处理字符串,必将是提高整体性能的关键所在. 1.字符串对象及其特点 Java中八大基本数据类型没有Str ...

  3. String字符串性能优化的探究

    一.背景 String 对象是我们使用最频繁的一个对象类型,但它的性能问题却是最容易被忽略的.String 对象作为 Java 语言中重要的数据类型,是内存中占用空间最大的一个对象,高效地使用字符串, ...

  4. C#中那些[举手之劳]的性能优化

    隔了很久没写东西了,主要是最近比较忙,更主要的是最近比较懒...... 其实这篇很早就想写了 工作和生活中经常可以看到一些程序猿,写代码的时候只关注代码的逻辑性,而不考虑运行效率 其实这对大多数程序猿 ...

  5. Android性能优化之利用LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...

  6. Mysql - 性能优化之子查询

    记得在做项目的时候, 听到过一句话, 尽量不要使用子查询, 那么这一篇就来看一下, 这句话是否是正确的. 那在这之前, 需要介绍一些概念性东西和mysql对语句的大致处理. 当Mysql Server ...

  7. 【腾讯Bugly干货分享】跨平台 ListView 性能优化

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/FbiSLPxFdGqJ00WgpJ94yw 导语 精 ...

  8. CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化

    一.浏览器兼容 1.1.概要 世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题.不同浏览器其内核亦不尽相同,相同内核的版本不同,相同版本的内核浏览器品牌不一样,各种运 ...

  9. 记录一次bug解决过程:可维护性和性能优化

    一.总结 使用某些变量的地方在2次以上的,强烈建议使用枚举值来维护变量,日后方便扩展. 查数据库的方法调用,能合并就净量去合并. 二.Bug描述 枚举变量的维护以及方法使用: public class ...

随机推荐

  1. NOIP 2014 普及组 T4 子矩阵

    [题意] 已知:n,m,r,c,a[i][j] (1 ≤ n ≤ 16, 1 ≤ m ≤ 16,1 ≤ a[i][j] ≤1000,1 ≤ r ≤ n, 1 ≤ c ≤ m) 条件:矩阵的分值定义为每 ...

  2. webstorm注释写出的提示

    写出这种代码提示的方法是 在一个函数上方打出 /** 然后敲回车就出出来 没达到上面的效果,自己手动写上即可. 这样的好处是: 当你写代码用到此方法的时候会有参数类型提示,如图

  3. java复用和传参

    java复用和传参的三种方法总结: (1) 直接在一个类中调用函数 : 1 package test1; 2 3 public class a 4 { 5 public static void get ...

  4. selenium+python笔记10

    #!/usr/bin/env python # -*- coding: utf-8 -*- """ 我们多添加一些测试场景,比如:删除邮件,查找邮件,发送邮件等等 &qu ...

  5. Ajax请求中带有IPv6地址后的百分号的问题

    IPv6地址后的百分号: 对于连入网络但没有IPv6路由器或DHCPv6服务器的IPv6客户端,它们始终使用fe80::/64链路本地网络地址.如果运行Windows的计算机中有多个网络适配器连接到不 ...

  6. C++格式化输入输出

    要实现格式化输入输出,程序需要包含 iostreams 标准标头 <iomanip> 以定义几个各自采用单个参数的操控器. 备注: 其中每个操控器都返回重载 basic_istream&l ...

  7. 算法——js(Fibonacci数列)

    斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家列昂纳多·斐波那契(Leonardoda Fibonacci[1]  )以兔子繁殖为例子而引入,故又称为“兔子数列”,指 ...

  8. 337. House Robber III——树的题目几乎都是BFS、DFS,要么递归要么循环

    The thief has found himself a new place for his thievery again. There is only one entrance to this a ...

  9. Loadrunner 使用检查点

    在使用loadrunner 测试时,比如我们在登陆时,我们希望说登录是否成功.这个时候我可以使用检查点函数. 检查登录后,页面上是否返回了某个标识,这样我们可以根据标识判断登录事务是否成功.   现在 ...

  10. ruby开源项目之Octopress:像黑客一样写博客(zhuan)

    ruby开源项目之Octopress:像黑客一样写博客 百度权重查询 词库网 网站监控 服务器监控 SEO监控 Swift编程语言教程 今年一直推荐的一种写作方式.markdown语法快速成文,git ...