string是我们经经常使用到的一个类型,事实上有时候认为敲代码就是在重复的操作字符串,这是C的特点,在java中。jdk非常好的封装了关于字符串的操作。三个类String 、StringBuffer 、 StringBuilder .这三个类基本上满足了我们在不同情景下使用字符串的需求。

一、String

JDK的解释是 “Strings are constant; their valuescannot be changed after they are created”也就是说String对象一旦被创建就是固定不变的了,这种一点优点就是能够多线程之间訪问,由于仅仅读不写。

普通情况下我们以以下两种方式创建一个String对象

Stringstr1 = “Liangcs”;

Stringstr2 = new String(“Laingcs”);

两种方式是有差别的,这和java的内存管理有关,前面已经说过,string创建之后是不可变的。所以依照第一种方式创建的字符串会放在栈里。更确切的是常量池中,常量池就是用来保存在编译阶段确定好了大小的数据,一般我们定义的int等基本数据类型就保存在这里。

其详细的一个流程就是,编译器首先检查常量池,看看有没有一个“string”,假设没有则创建。

假设有的话,则则直接把str1指向那个位置。

另外一种创建字符串的方法是通过newkeyword,还是java的内存分配,java会将new的对象放在堆中,这一部分对象是在执行时创建的对象。所以我们每一次new的时候,都会创建不同的对象,即便是堆中已经有了一个一模一样的。

写一个小样例

<span style="font-size:18px;">String str1 = "string";
String str4 = "string";
String str2 = newString("string");
String str3 = newString("string"); /*用于測试两种创建字符串方式的差别*/
System.out.println(str1 == str4);
System.out.println(str2 == str3);
System.out.println(str3 == str1); str3 =str3.intern(); //一个不常见的方法
System.out.println(str3 == str1);
这个的执行结果是
true //解释:两个字符串的内容全然同样,因而指向常量池中的同一个区域
false //解释:每一次new都会创建一个新的对象
false // 解释: 注意==比較的是地址,不不过内容
true //介绍一下intern方法,这种方法会返回一个字符串在常量池中的一个地址,假设常量池中有与str3内容同样的string则返回那个地址。假设没有,则在常量池中 创建一个string后再返回。实际上,str3如今指向了str1的地址。</span>

非常多人有这种疑问就是既然string是不变的,那么为什么str1 + "some"是合法的,事实上。每次对string进行改动,都会创建一个新的对象。

所以假设须要对一个字符串不断的改动的话,效率是非常的低的,由于堆的优点是能够动态的添加空间,劣势就是分配新的空间消耗是非常大的。比方我们看以下的測试。

<span style="font-size:18px;">        long start =System.currentTimeMillis();

        for(int i = 0; i < 50000; i++)
{
str1+= " ";
}
long end = System.currentTimeMillis();
System.out.println("the run timeis "+(end -start)+" ms");</span>

上执行结果是the run time is 3538 ms   假设你把循环的次数后面再添加几个0就会更慢。

由于每一次循环都在创建心的对象。那么JDK怎样解决问题?

以下就要说

二、StringBuffer。

StringBuffer是一个线程安全的,就是多线程訪问的可靠保证。最重要的是他是可变的,也就是说我们要操作一个常常变化的字符串,能够使用这个类,主要的方法就是append(与string的concat方法相应)和insert方法,至于怎么使用,就不多讲了。大家能够自己查看API。

<span style="font-size:18px;">       StringBuilder sb = new StringBuilder("string builder");
StringBuffer sf = newStringBuffer("string buffer");
long start =System.currentTimeMillis();
for(int i = 0; i < 50000; i++)
{
//str1+= " ";
sb.append(" ");
}
long end = System.currentTimeMillis();
System.out.println("the run timeis "+(end -start)+" ms");</span>

測试一下,这次仅仅须要8ms。这就是效率。

三、StringBuilder

那么接下来,就要问StringBuilder是干什么的。事实上这个才是我们尝使用的。这个就是在jdk 1.5版本号后面加入的新的类。前面说StringBuffer是线程同步的。那么非常多情况下。我们仅仅是使用一个线程,那个同步势必带来一个效率的问题,StringBuilder就是StringBuffer的非线程同步的版本号,二者的方法几乎相同。仅仅是一个线程安全(适用于多线程)一个没有线程安全(适用于单线程)。

事实上看了一下jdk源码就会发现,StringBuffer就是在各个方法上加上了keywordsyncronized

StringBuilder也是一个可变的字符串对象。他与StringBuffer不同之处就在于它是线程不安全的,基于这点,它的速度一般都比StringBuffer快。与StringBuffer一样,StringBuider的主要操作也是append与insert方法。

这两个方法都能有效地将给定的数据转换成字符串。然后将该字符串的字符加入或插入到字符串生成器中。

三者比較

简要的说。 String 类型和 StringBuffer 类型的主要性能差别事实上在于 String 是不可变的对象(为什么?问问 Java 的设计者吧,为什么 String 不是原生类型呢?)因此在每次对 String 类型进行改变的时候事实上都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以常常改变内容的字符串最好不要用 String ,由于每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会開始工作。那速度是一定会相当慢的。这里尝试举个不是非常恰当的样例:

<span style="font-size:18px;">       String S1 = “abc”;
For(int I = 0 ; I < 10000 ; I++) // For 模拟程序的多次调用
{
S1+ = “def”;
S1= “abc”;
}</span>

假设是这种话,到这个 for 循环完成后,假设内存中的对象没有被 GC 清理掉的话。内存中一共同拥有 上 万个了。惊人的数目,而假设这是一个非常多人使用的系统,这种数目就不算非常多了。所以大家使用的时候一定要小心。

而假设是使用 StringBuffer 类则结果就不一样了。每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象。再改变对象引用。

所以在普通情况下我们推荐使用StringBuffer ,特别是字符串对象常常改变的情况下。而在某些特别情况下, String 对象的字符串拼接事实上是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是下面的字符串对象生成中。 String 效率是远要比 StringBuffer 快的:

String S1 = “This is only a” + “simple” + “ test”;

StringBuffer Sb = newStringBuilder(“This is only a”).append(“ simple”).append(“ test”);

你会非常吃惊的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 竟然速度上根本一点都不占优势。事实上这是 JVM 的一个把戏,在 JVM 眼里。这个

String S1 = “This is only a” + “simple” + “test”; 事实上就是:

String S1 = “This is only asimple test”; 所以当然不须要太多的时间了。但大家这里要注意的是,假设你的字符串是来自另外的 String 对象的话,速度就没那么快了。譬如:

String S2 = “This is only a”;

String S3 = “ simple”;

String S4 = “ test”;

String S1 = S2 +S3 + S4;

这时候 JVM 会规规矩矩的依照原来的方式去做。 S1 对象的生成速度就不像刚才那么快了,一会儿我们能够来个測试作个验证。

由此我们得到第一步结论:

在大部分情况下 StringBuffer >String

而 StringBuilder 跟他们比又怎么样呢?先简介一下, StringBuilder 是 JDK5.0 中新添加的一个类。它跟 StringBuffer 的差别看以下的介绍(来源 JavaWorld ):

Java.lang.StringBuffer 线程安全的可变字符序列。类似于 String 的字符串缓冲区。但不能改动。可将字符串缓冲区安全地用于多个线程。

能够在必要时对这些方法进行同步。因此随意特定实例上的全部操作就好像是以串行顺序发生的,该顺序与所涉及的每一个线程进行的方法调用顺序一致。

每一个字符串缓冲区都有一定的容量。

仅仅要字符串缓冲区所包括的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。

假设内部缓冲区溢出。则此容量自己主动增大。从 JDK 5.0 開始,为该类增添了一个单个线程使用的等价类。即 StringBuilder 。

与该类相比,通常应该优先使用 StringBuilder 类,由于它支持全部同样的操作,但由于它不运行同步。所以速度更快。

可是假设将 StringBuilder 的实例用于多个线程是不安全的。须要这种同步,则建议使用 StringBuffer 。

这样说预计大家都能明确他们之间的差别了。那么以下我们再做一个一般性推导:

在大部分情况下 StringBuilder >StringBuffer

因此,依据这个不等式的传递定理: 在大部分情况下

StringBuilder > StringBuffer> String

对于三者使用的总结:

1.假设要操作少量的数据用 String

2.单线程操作字符串缓冲区 下操作大量数据  StringBuilder

3.多线程操作字符串缓冲区 下操作大量数据  StringBuffer

四、经常使用串操作

1、字符串比較

equals()   ------推断内容是否同样。

compareTo() ------推断字符串的大小关系。

compareToIgnoreCase(String int)    ------在比較时忽略字母大写和小写。

== ------推断内容与地址是否同样。

equalsIgnoreCase() ------忽略大写和小写的情况下推断内容是否同样。

reagionMatches() ------对字符串中的部分内容是否同样进行比較(详情请參考API)。

      2、字符串查找

charAt(int index) ------返回指定索引index位置上的字符,索引范围从0開始。

indexOf(String str)------从字符串開始检索str,并返回第一次出现的位置,未出现返回-1。

indexOf(String str,intfromIndex);------从字符串的第fromIndex个字符開始检索str。

lastIndexOf(String str)------查找最后一次出现的位置。

lastIndexOf(String str,intfromIndex)----从字符串的第fromIndex个字符查找最后一次出现的位置。

starWith(String prefix,inttoffset)-----測试此字符串从指定索引開始的子字符串是否以指定前缀開始。

starWith(String prefix)------測试此字符串是否以指定的前缀開始。

endsWith(String suffix)------測试此字符串是否以指定的后缀结束。

      3、字符串截取

          public String subString(int beginIndex)------返回一个新的字符串,它是此字符串的一个子字符串。

public String subString(int beginIndex,int endIndex)------返回的字符串是从beginIndex開始到endIndex-1的串。

     4、字符串替换

public String replace(char oldChar。char newChar)。

public String replace(CharSequence target,CharSequence replacement)------把原来的etarget子序列替换为replacement序列。返回新串。

public String replaceAll(String regex。String replacement)------用正則表達式实现对字符串的匹配。注意replaceAll第一个參数为正則表達式,鄙人以前深受其害。

通过我自己的学习,我感觉事实上最好的资料就是JDK的API,能够好好利用。

四:Java之字符串操作String、StringBuffer和StringBuilder的更多相关文章

  1. JAVA作业—字符串操作

    ------------恢复内容开始------------ ------------恢复内容开始------------ ------------恢复内容开始------------ ------- ...

  2. Java String, StringBuffer和StringBuilder实例

    1- 分层继承2- 可变和不可变的概念3- String3.1- 字符串是一个非常特殊的类3.2- String 字面值 vs. String对象3.3- String的方法3.3.1- length ...

  3. Java的字符串操作

    目录 Java的字符串操作 一.不同字符串操作的对比 1.1 C++中const修饰指针 const在星号的左边,是被指向的常量不可变 const在星号的右边,是指针的指向不可变 二. Java字符串 ...

  4. Java的字符串操作一些简单的思考

    Java的字符串操作 1 .1不可变的String String对象事不可变的,String类中的每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改后的字符 ...

  5. [改善Java代码]正确使用String,StringBuffer,StringBuilder

    CharSequence接口有三个实现类与字符串有关:String,StringBuffer,StringBuffer.虽然它们都与字符串有关,但是其处理机制是不同的. String类是不可改变的量, ...

  6. Java基础-字符串(String)常用方法

    Java基础-字符串(String)常用方法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.java的API概念 Java的API(API:Application(应用) Pr ...

  7. String,StringBuffer与StringBuilder

    1. String,StringBuffer与StringBuilder的区别 String:存储在常量池中:是不可变的字符序列,任何对String值的改变都会引发新的String对象的生成,因此执行 ...

  8. String, StringBuffer and StringBuilder

    一 String 概述: String 被声明为 final,因此它不可被继承. 在 Java 8 中,String 内部使用 char 数组存储数据. public final class Stri ...

  9. String,StringBuffer和StringBuilder

    String,StringBuffer和StringBuilder分别应该在什么情况下使用? String 是Java的字符串类,其实质上也是用Char类型存储的,但是除了hash属性,其他的属性都声 ...

随机推荐

  1. PSP需求分析文档

    PSP软件需求分析文档 刘杰 1.       引言 1.1  背景 开发项目经常延期不能按时提交,甚至不能给出明确的延迟时间 1.2  术语 PSP,数据库 2.       任务概述 2.1  目 ...

  2. 项目经验——Sql server 数据库的备份和还原____还原数据库提示“介质集有2个介质簇,但只提供了1个。必须提供所有成员” .

    在对数据库备份与还原的过程中,我遇到一个问题“介质集有2个介质簇,但只提供了1个.必须提供所有成员”,下面详细的介绍一下遇到问题的经过与问题解决的方法! 一.备份与还原遇到的问题描述与解决方法: 前两 ...

  3. [Windows Server 2008] Windows防火墙设置

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:如何开启W ...

  4. 【译】x86程序员手册24-第7章 多任务

    Chapter 7 Multitasking 多任务 To provide efficient, protected multitasking, the 80386 employs several s ...

  5. Hibernate框架之Criteria 详解

    自从学数据库以来,从SQL查询-HQL查询-到Criteria 查询.有人问我:掌握一种查询语句不就可以吗,为什么还要学Criteria 查询?我回答道:用到特定于数据库的SQL 语句,程序本身会依赖 ...

  6. webpack常见问题

    概念问题一:什么是webpack和grunt和gulp有什么不同 答案:Webpack是一个模块打包器,他可以递归的打包项目中的所有模块,最终生成几个打包后的文件.他和其他的工具最大的不同在于他支持c ...

  7. DWG转PDF

    DWG转PDF DWG转换PDF有两种方法,一种是利用PDF打印机,一种是利用专业软件: 利用PDF打印机最直接,但是不能批量打印,下面讲一下利用专业软件如何进行批量转换,在这里以梦想CAD软件(Mx ...

  8. 深度完整的了解MySQL锁

    今天就讲讲MySQL的锁 主讲:Mysql的悲观锁 和 乐观锁官方:If you query data and then insert or update related data within th ...

  9. Django-前后台的数据交互

    Django 从后台往前台传递数据时有多种方法可以实现. 最简单的后台是这样的: from django.shortcuts import render def main_page(request): ...

  10. pandas处理各类表格数据

    经常遇到Python读取excel和csv还有其他各种文件的内容.json还有web端的读取还是比较简单,但是excel和csv的读写是很麻烦.这里记录了pandas库提供的方法来实现文本内容和Dat ...