字符串是软件开发中最重要的对象之一。通常,字符串对象在内存中是占据了最大的空间块,因此如何高效地处理字符串,必将是提高整体性能的关键所在。

1.字符串对象及其特点

Java中八大基本数据类型没有String类型,因为String类型是Java对char数组的进一步封装。

String类的实现主要由三部分组成:char数组,offset偏移量,String的长度。

String类型有三个基本特点:

  1. 不变性

    不变性是指String对象一旦生成,则不能再对它进行改变。

    不变性的作用在于当一个对象需要被多线程共享,并且频繁访问时,可以省略同步和锁等待的时间,从而大幅提高系统性能。

  2. 针对常量池的优化

    当两个String对象拥有相同的值时,它们只引用常量池中的同一个拷贝。

  3. 类的final定义

    作为final类的String对象在系统中不能有任何子类,这是对系统安全性的保护!

1.1 subString()方法的内存泄漏

关于这一点,在JDK的1.7及以后就已经解决了!

在1.7之前,subString()方法截取字符串只是移动了偏移量,截取之后的字符串实际上还是原来的大小。

现在,当使用subString()方法截取字符串时会把截取后的字符串拷贝到新对象。

1.2 字符串分割与查找

1、原始的String.split()

String.split()方法使用简单,功能强大,支持正则表达式,但是,在性能敏感的系统中频繁的使用这个方法是不可取的。

注意 * ^ : | .  这些符号记得\\转义

2、使用效率更高的StringTokenizer类分割字符串

StringTokenizer类是JDK中提供的专门用来处理字符串分割的工具类。构造方法:

public StringTokenizer(String str, String delim, boolean returnDelims) 

其中str是要分割的字符串,delim是分割符,returnDelims是否返回分隔符,默认false。

  String s = "a;b;c";
  StringTokenizer stringTokenizer = new StringTokenizer(s, ";", false);
  System.out.println(stringTokenizer.countTokens());
  while (stringTokenizer.hasMoreTokens()) {
      System.out.println(stringTokenizer.nextToken());
  }

3、最优化的字符串分割方式

indexOf()方法是一个执行速度非常快的方法,subString()是采用了时间换空间技术,因此速度相对快。

    public static List<String> mySplit(String str, String delim){
        List<String> stringList = new ArrayList<>();
        while(true) {
            int k = str.indexOf(delim);
            if (k < 0){
                stringList.add(str);
                break;
            }
            String s = str.substring(0, k);
            stringList.add(s);
            str = str.substring(k+1);
        }
        return stringList;
    }

4、三种分割方法的对比与选择

split()方法功能强大,但是效率最差;

StringTokenizer性能优于split方法,能用StringTokenizer就没必要用split();

自己实现的分割算法性能最好,但代码的可读性和系统的可维护性最差,只有当系统性能成为主要矛盾时,才推荐使用该方法。

5、高效率的charAt方法

charAt(int index) 返回指定索引处的 char 值。功能和indexOf()相反,效率却一样高。

6、字符串前后辍判断

public boolean startsWith(String prefix) 测试此字符串是否以指定的前缀开始

public boolean endsWith(String suffix) 测试此字符串是否以指定的后缀结束

这两个Java内置函数效率远远低于charAt()方法。单元测试:

    @Test
    public void test(){
        String str = "hello";
        if (str.charAt(0)=='h'&&str.charAt(1)=='e'){
            System.out.println(true);
        }
        if (str.startsWith("he")){
            System.out.println(true);
        }
    }

1.3 StringBuffer和StringBuilder

1、String常量的累加操作

String s = "123"+"456"+"789";

虽然从理论上说字符串的累加的效率并不高,但该语句执行耗时为0;反编译代码后,我们发现代码是

String s = "123456789";

显然,是Java在编译时做了充分的优化。因此,并没有想象中那样生成大量的String实例。

对于静态字符串的连接操作,Java在编译时会进行彻底的优化,将多个连接操作的字符串在编译时合成一个单独的长字符串。

2、String变量累加的操作

  String str = "hello";
  str+="word";
  str+="!!!";

我们利用“+=”改变字符串内容的值,实际上字符串根本没有改变。

str+="word" 时,堆内存开辟了word的内存空间和helloword的两个内存空间(相当于实例化了两个String对象),并把str的引用指向了helloword,原来的helloword成为了垃圾被JVM回收。

3、concat() 连接字符串

String的concat()是专门用于字符串连接操作的方法,效率远远高于“+”或者“+=”。

4、StringBuffer和StringBuilder

不用多说了,就是为字符串连接而生的,效率最高。不同的是,StringBuffer几乎对所有的方法都做了同步,StringBuilder并没有做任何同步,效率更高一些。只不过在多线程系统中,StringBuilder无法保证线程安全,不能使用。

5、容量参数

StringBuffer和StringBuilder的是对String的封装,String是对char数组的封装。是数组就有大小,就有不够用的时候,不够用只能扩容,也就是把原来的再复制到新的数组中。合适的容量参数自然能够减少扩容的次数,达到提高效率的目的。

在初始化时,容量参数默认是16个字节。在构造方法中指定容量参数:

public StringBuilder(int capacity) 

1.4 附一些实用的方法

判断字符串相等(忽略大小写)

equalsIgnoreCase(String anotherString)

判断是否存在子字符串(返回布尔类型)

contains(CharSequence s)

将指定字符串连接到此字符串的结尾

concat(String str)

使用指定的格式字符串和参数返回一个格式化字符串

format(String format, Object... args)

使用默认语言环境的规则将此 String 中的所有字符都转换为小写。

toLowerCase() 

使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

toUpperCase() 

返回字符串的副本,忽略前导空白和尾部空白。

trim() 

使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

String replaceAll(String regex, String replacement)

按字典顺序比较两个字符串,不考虑大小写。

int compareToIgnoreCase(String str)
  • 如果参数字符串等于此字符串,则返回值 0;
  • 如果此字符串小于字符串参数,则返回一个小于 0 的值;
  • 如果此字符串大于字符串参数,则返回一个大于 0 的值。

本文参考《Java程序性能优化》葛一鸣著

Java性能优化之String字符串优化的更多相关文章

  1. JAVA基础——重新认识String字符串

    深入剖析Java之String字符串 在程序开发中字符串无处不在,如用户登陆时输入的用户名.密码等使用的就是字符串. 在 Java 中,字符串被作为 String 类型的对象处理. String 类位 ...

  2. Java性能之synchronized锁的优化

    synchronized / Lock 1.JDK 1.5之前,Java通过synchronized关键字来实现锁功能 synchronized是JVM实现的内置锁,锁的获取和释放都是由JVM隐式实现 ...

  3. 【原创】使用Java进行Clob转String字符串

    背景 oracle字段类型varchar2最大长度4000,超过的怎么办 解决 使用clob类型,大字段,无长度限制 问题 使用Java的JDBC读取的RS获取的clob类型无法正常使用,封装的rs. ...

  4. Java 性能优化之 String 篇

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

  5. java性能优化--字符串优化处理

    String对象 String对象是java中重要的数据类型,在大部分情况下我们都会用到String对象.其实在Java语言中,其设计者也对String做了大量的优化工作,这些也是String对象的特 ...

  6. String字符串性能优化的几种方案

    String字符串是系统里最常用的类型之一,在系统中占据了很大的内存,因此,高效地使用字符串,对系统的性能有较好的提升. 针对字符串的优化,我在工作与学习过程总结了以下三种方案作分享: 一.优化构建的 ...

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

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

  8. JAVA程序优化之字符串优化处理

    字符串是软件开发中最为重要的对象之一.通常,字符串对象或其等价对象(如char数组),在内存中总是占据了最大的空间块.因此如何高效地处理字符串,必将是提高系统整体性能的关键所在. 1.String对象 ...

  9. Java性能优化的50个细节(珍藏版)

    原文地址:https://www.toutiao.com/i6595499804082569742/ 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重 ...

随机推荐

  1. (后端)Spring手动回滚事务

    百度上查资料获得的 throw new RuntimeException(); 或者  TransactionAspectSupport.currentTransactionStatus().setR ...

  2. canvas学习总结四:绘制虚线

    上一章节我们说到,线性路径的绘制,主要利用movoTo(),lineTo()等方法,当然 Canvas 2D API 也提供了虚线的绘制方法,CanvasRenderingContext2D.setL ...

  3. ZooKeeper使用命令大全

    stat path [watch]    set path data [version]    ls path [watch]    delquota [-n|-b] path    ls2 path ...

  4. 洗礼灵魂,修炼python(66)--爬虫篇—BeauitifulSoup进阶之“我让你忘记那个负心汉,有我就够了”

    说明一下,这个标题可能有点突兀,结合上一篇一起看就行 前面已经对BeautifulSoup有了了解了,相信你基本已经学会怎么获取网页数据了,那么BeautifulSoup这么吊,还有没有其他的功能呢? ...

  5. Linux内存描述之概述--Linux内存管理(一)

    1 前景回顾 1.1 UMA和NUMA两种模型 共享存储型多处理机有两种模型 均匀存储器存取(Uniform-Memory-Access,简称UMA)模型 将可用内存以连续方式组织起来, 非均匀存储器 ...

  6. java操作elasticsearch实现聚合查询

    1.max 最大值 //max 求最大值 @Test public void test30() throws UnknownHostException{ //1.指定es集群 cluster.name ...

  7. 《Java大学教程》—读后总结

    1.坚持就是胜利. 中间启动了许多次,但又因为各种原因被停.就连闭关学习期间,也多次想放弃,总觉得太简单,最后还是选择了这本书而放弃了其他书,原因是马上要还书了,"书是非借不能读!" ...

  8. 比MR至少快5倍的神器,竟然是它

    Hive简介 Hive是一个基于 Hadoop 的开源数据仓库工具,用于存储和处理海量结构化数据.它最初是应Facebook对每天产生的海量新兴社会网络数据进行管理和机器学习的需求而产生和发展的,Hi ...

  9. 大数据计算平台Spark内核全面解读

    1.Spark介绍 Spark是起源于美国加州大学伯克利分校AMPLab的大数据计算平台,在2010年开源,目前是Apache软件基金会的顶级项目.随着Spark在大数据计算领域的暂露头角,越来越多的 ...

  10. (转)springcloud(一):大话Spring Cloud

    http://www.ityouknow.com/springcloud/2017/05/01/simple-springcloud.html 研究了一段时间Spring Boot了准备向Spring ...