在Java语言中,字符串数据实际上由String类所实现的。Java字符串类分为两类:一类是在程序中不会被改变长度的不变字符串;另一类是在程序中会被改变长度的可变字符串。Java环境为了存储和维护这两类字符串提供了 String和StringBuffer两个类(在JDK1.5版本后出现了StringBuilder,该类被设计用作 StringBuffer 的一个简易替换)。
一、字符串(String)
1、字符串概念了解
程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
字符串是常量,字符串对象表示固定长度的字符序列,它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String
对象是不可变的,所以可以共享。String类可能是Java程序中使用的最频繁的类了。(注意:String类是被final修饰的,不能被继承,String底层实现其实是字符数组。)
2、字符串对象的创建
1、使用字符串常量直接初始化一个String对象。
2、使用String的构造方法初始化字符串对象。
如:String str = new String("this is a string");
实际运用中,我们要避免第二种方式,第二种方式创建了两个String对象。首先,Java虚拟机创建了String对象“abc”。然后,Java虚拟机创建一个新的String对象,并把字符串“abc”传入构造函数。这是一次完全没有必要的构造,既影响了性能,也提高了代码阅读难度。
如: String str = "\t\n";
3、字符串的常见操作
- String str = "this is a string!";
- System.out.println(str.indexOf('i')); // 输出结果为:2
- System.out.println(str.indexOf('!')); // 输出结果为:16
- System.out.println(str.indexOf('y')); // 输出结果为:-1
- // 重载方法:int indexOf(String str)
- // 返回指定子字符串在此字符串中第一次出现处的索引。
- System.out.println(str.indexOf("str"));// 输出结果为:10
- System.out.println(str.lastIndexOf('s')); // 输出结果为:10
- // 常用
- String str1 = "I love" + " you!";
- System.out.println(str1); // 输出结果为:I love you!
- // 少用
- String str2 = "abc".concat("xyz");
- System.out.println(str2);// 输出结果为:abcxyz
- String str = "this is a string!";
- System.out.println("字符串的长度为:" + str.length()); // 输出结果为:字符串的长度为:17
- System.out.println(str.charAt(5)); // 输出结果为:i
4、 字符串前后缀、判空、大小写转换即子串查询
boolean endsWith(String suffix):判断此字符串是否以指定的后缀结束。
boolean isEmpty() :当且仅当 length() 为 0 时返回 true。
boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true。
String toUpperCase():使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
String toLowerCase():使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
- String str = "This is a String!";
- System.out.println(str.startsWith("Th")); // 输出结果为:true
- System.out.println(str.startsWith("a"));// 输出结果为:false
- System.out.println(str.endsWith("ing!"));// 输出结果为:true
- System.out.println(str.endsWith("ing"));// 输出结果为:false
- System.out.println(str.toUpperCase());// 输出结果为:THIS IS A STRING!
- System.out.println(str.toLowerCase());// 输出结果为:this is a string!
- System.out.println(str.contains("is"));// 输出结果为:true
- System.out.println(str.isEmpty());// 输出结果为:false
- str = "";
- System.out.println(str.isEmpty());// 输出结果为:true
5、字符串与基本数据类型转换
- String x = String.valueOf(12);// 基本数据类型转字符串
- System.out.println(x);
- int a = 5; // 基本数据类型转字符串
- Integer i = new Integer(a);
- i.toString();
- // 顺便提下
- int y = Integer.parseInt("21"); // 字符串转基本数据类型
- System.out.println(y);
6、字符串转字符数组
- import java.util.Scanner;
- public class Demo {
- public static void main(String[] args) {
- /*
- * 从控制台输入字符串,计算出该字符串中
- * 大写字母出现的个数
- * 小写字母出现的个数
- * 数字出现的个数
- * 特殊字符出现的个数
- */
- Scanner scan = new Scanner(System.in);
- System.out.println("请输入字符串:");
- String str = scan.nextLine();
- int num1, num2, num3, num4;
- num1 = num2 = num3 = num4 = 0;
- char[] strs = str.toCharArray();// 将此字符串转换为一个新的字符数组。
- for (char s : strs) {
- if (s >= 'A' && s <= 'Z') {
- num1++;
- } else if (s >= 'a' && s <= 'z') {
- num2++;
- } else if (s >= '0' && s <= '9') {
- num3++;
- } else {
- num4++;
- }
- }
- System.out.println("大写字母:" + num1);
- System.out.println("小写字母:" + num2);
- System.out.println("数字:" + num3);
- System.out.println("特殊字符:" + num4);
- }
- }
7、字符串去空与替换
String replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
- String str = " this is a string! ";
- System.out.println(str.trim());// 运行结果为:this is a string!
- System.out.println(str.replace("is", "xyz"));// 运行结果为: thxyz xyz a string!
8、 字符串分割与截取
String substring(int beginIndex) :返回一个新的字符串,它包含此字符串中索引为beginIndex后的所有字符
String substring(int beginIndex, int endIndex) :返回一个新字符串,它包含此字符串中从索引beginIndex到endIndex之间的所有字符
- String str = "乒乓球-篮球-排球";
- System.out.println("从第5个字符截取到末尾的结果:" + str.substring(4));
- System.out.println("从第5个字符截取到第6个字符的结果:" + str.substring(4, 6));
- // 注意包含头,不包含尾
- System.out.print("分割后字符串数组中的元素依次是:");
- String[] strArray = str.split("-");
- for (int i = 0; i < strArray.length; i++) {
- if (i != strArray.length - 1) {
- System.out.print(strArray[i] + " ");// 如果不是数组的最后一个元素,在元素后面加空格。
- } else {
- System.out.println(strArray[i]);// 数组的最后一个元素后面不加逗号
- }
- }
从第5个字符截取到第6个字符的结果:篮球
分割后字符串数组中的元素依次是:乒乓球 篮球 排球
9、字符串相等判断
- String str1 = new String("xyz");
- String str2 = new String("xyz");
- System.out.println(str1 == str2);// 输出结果为:false
- System.out.println(str1.equals(str2)); // 输出结果为:true
- // 1、str1和str2分别指向不同的对象,那么str1 == str2将返回false
- // 用equals方法,该方法比较的是字符串的内容是否相同。
- String str3 = "xyz";
- String str4 = "xyz";
- System.out.println(str3 == str4);// 输出结果为:true
- System.out.println(str3.equals(str4)); // 输出结果为:true
- // 2、用"=="运算符,该运算符表示指向字符串的引用是否相同,
- // 上面: String str3="xyz";String str4 = "xyz",那么str3 == str4将返回true。
- // 这是因为在java中字符串的值是不可改变的,相同的字符串在内存中只会存一份,
- // 所以a和b指向的是同一个对象;
二、StringBuffer
1、StringBuffer的了解
由于字符串是常量,因此一旦创建,其内容和长度是不可改变的。如果需要对一个字符串进行修改,则只能创建新的字符串。为了方便对字符串进行修改,在JDK中提供了StringBuffer类(也称字符串缓冲区)。StringBuffer类和String类最大的区别在于它的内容和长度是可以改变的。StringBuffer类似一个字符容器,当在其中添加或删除字符时,并不会产生新的StringBuffer对象。
2、StringBuffer的常用方法(操作)
StringBuffer insert(int offset, String str) :将字符串str插入offset位置
StringBuffer deleteCharAt(int index):移除此序列指定位置的字符
StringBuffer delete(int start,int end):删除StringBuffer对象指定范围内的字符或字符串序列
StringBuffer replace(int start,int end,String str):在StringBuffer对象中替换指定的字符或字符串序列。
void setCharAt(int index,char ch):修改指定位置的index处的字符序列
String toString():返回StringBuffer缓冲区中的字符串
StringBuffer reverse():将此字符序列用其反转形式取代。
- public class Demo {
- public static void main(String[] args) {
- System.out.println("1、添加------------");
- add();
- System.out.println("2、删除------------");
- delete();
- System.out.println("3、修改------------");
- alter();
- }
- public static void add() {
- StringBuffer sb = new StringBuffer();// 定义一个字符串缓冲区
- sb.append("abcdefg");// 添加到StringBuffer中
- System.out.println("append添加结果:" + sb);
- sb.insert(2, "123");// 在指定位置插入字符串
- System.out.println("insert插入结果:" + sb);
- }
- public static void delete() {
- StringBuffer sb = new StringBuffer("abcdefg");// 定义一个字符串缓冲区
- sb.delete(1, 5);// 包含头,不包含尾
- System.out.println("删除指定范围的结果:" + sb);
- sb.deleteCharAt(2);
- System.out.println("删除指定位置的结果:" + sb);
- sb.delete(0, sb.length());
- System.out.println("清空缓冲区的结果是:" + sb);
- }
- public static void alter() {
- StringBuffer sb = new StringBuffer("abcdefg");// 定义一个字符串缓冲区
- sb.setCharAt(1, 'q');
- System.out.println("修改指定位置字符的结果:" + sb);
- sb.replace(1, 3, "xyz");// 包含头,不包含尾
- System.out.println("替换指定位置字符串的结果:" + sb);
- System.out.println("字符串反转后的结果:" + sb.reverse());
- }
- }
运行结果为:
append添加结果:abcdefg
insert插入结果:ab123cdefg
2、删除------------
删除指定范围的结果:afg
删除指定位置的结果:af
清空缓冲区的结果是:
3、修改------------
修改指定位置字符的结果:aqcdefg
替换指定位置字符串的结果:axyzdefg
字符串反转后的结果:gfedzyxa
三、StringBuilder
1、StringBuilder的了解
JDK1.5开始,StringBuilder是一个可变的字符序列。此类提供一个与 StringBuffer 兼容的
API,但不保证同步。该类被设计用作 StringBuffer
的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比
StringBuffer 要快。
2、StringBuilder的常用方法
3、String、StringBuffer和StringBuilder的区别
而StringBuilder和StringBuffer表示字符容器,其内容和长度都可以随时修改。在操作字符串时,如果该字符串仅用于表示数据类型,则使用String类即可,但是如果需要对字符串中的字符进行增删操作,则使用StringBuilder和StringBuffer类。使用
StringBuffer 类时,每次都会对 StringBuffer
对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
4、使用策略String、StringBuffer和StringBuilder的区别
1 String
String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。
String类的包含如下定义:
- /** The value is used for character storage. */
- private final char value[];
- /** The offset is the first index of the storage that is used. */
- private final int offset;
- /** The count is the number of characters in the String. */
- private final int count;
用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改。
2 StringBuffer(JDK1.0)
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。
Java.lang.StringBuffer线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
3 StringBuilder(JDK5.0)
StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。
java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
其构造方法如下:
构造方法 | 描述 |
StringBuilder() | 创建一个容量为16的StringBuilder对象(16个空元素) |
StringBuilder(CharSequence cs) | 创建一个包含cs的StringBuilder对象,末尾附加16个空元素 |
StringBuilder(int initCapacity) | 创建一个容量为initCapacity的StringBuilder对象 |
StringBuilder(String s) | 创建一个包含s的StringBuilder对象,末尾附加16个空元素 |
在大部分情况下,StringBuilder > StringBuffer。这主要是由于前者不需要考虑线程安全。
4 三者区别
String 类型和StringBuffer的主要性能区别:String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的
String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String
,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。
使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
在某些特别情况下, String 对象的字符串拼接其实是被 JavaCompiler 编译成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,例如:
- String s1 = “This is only a” + “ simple” + “ test”;
- StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
生成 String s1对象的速度并不比 StringBuffer慢。其实在Java Compiler里,自动做了如下转换:
Java Compiler直接把上述第一条语句编译为:
- String s1 = “This is only a simple test”;
所以速度很快。但要注意的是,如果拼接的字符串来自另外的String对象的话,Java Compiler就不会自动转换了,速度也就没那么快了,例如:
- String s2 = “This is only a”;
- String s3 = “ simple”;
- String s4 = “ test”;
- String s1 = s2 + s3 + s4;
这时候,Java Compiler会规规矩矩的按照原来的方式去做,String的concatenation(即+)操作利用了StringBuilder(或StringBuffer)的append方法实现,此时,对于上述情况,若s2,s3,s4采用String定义,拼接时需要额外创建一个StringBuffer(或StringBuilder),之后将StringBuffer转换为String;若采用StringBuffer(或StringBuilder),则不需额外创建StringBuffer。
5 使用策略
(1)基本原则:如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。
(2)不要使用String类的"+"来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。例如:
- String result = "";
- for (String s : hugeArray) {
- result = result + s;
- }
- // 使用StringBuilder
- StringBuilder sb = new StringBuilder();
- for (String s : hugeArray) {
- sb.append(s);
- }
- String result = sb.toString();
当出现上面的情况时,显然我们要采用第二种方法,因为第一种方法,每次循环都会创建一个String result用于保存结果,除此之外二者基本相同(对于jdk1.5及之后版本)。
(3)为了获得更好的性能,在构造 StringBuffer 或 StringBuilder 时应尽可能指定它们的容量。当然,如果你操作的字符串长度(length)不超过 16 个字符就不用了,当不指定容量(capacity)时默认构造一个容量为16的对象。不指定容量会显著降低性能。
(4)StringBuilder一般使用在方法内部来完成类似"+"功能,因为是线程不安全的,所以用完以后可以丢弃。StringBuffer主要用在全局变量中。
(5)相同情况下使用 StringBuilder 相比使用
StringBuffer 仅能获得 10%~15%
左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在
StringBuffer
上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用StringBuffer。
参考资料:
http://docs.oracle.com/javase/tutorial/java/data/buffers.html
http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4
Java API
Java编程基础-字符串的更多相关文章
-
Java入门——(1)Java编程基础
Java入门--(1)Java编程基础 第二章 Java编程基础 JAVA 代码的基本格式: 修饰符 class 类名{ 程序代码 } 2.1关键字:赋予了特殊含义的单词. 2.2标识符: ...
-
Java开发知识之Java编程基础
Java开发知识之Java编程基础 一丶Java的基础语法 每个语言都有自己的语法规范.例如C++ 入口点是main. 我们按照特定格式编写即可. Java也不例外. Java程序的语法规范就是 Ja ...
-
Java编程基础——数组和二维数组
Java编程基础——数组和二维数组 摘要:本文主要对数组和二维数组进行简要介绍. 数组 定义 数组可以理解成保存一组数的容器,而变量可以理解为保存一个数的容器. 数组是一种引用类型,用于保存一组相同类 ...
-
java编程基础二进制
0.java编程基础 01.二进制(原码,反码,补码) 02.位运算 03.移位运算符 二进制 原码,反码,补码 1.基本概念 二进制是逢2进位的进位制,0,1是基本算符. 现在的电子计算机技术全部使 ...
-
Java编程基础-面向对象(中)
本章承接Java编程基础-面向对象(上)一文. 一.static关键字 在java中,定义了一个static关键字,它用于修饰类的成员,如成员变量.成员方法以及代码块等,被static修饰的成员具备一 ...
-
Java编程基础——流程控制
Java编程基础——流程控制 摘要:本文主要介绍Java编程中的流程控制语句. 分类 流程控制指的是在程序运行的过程中控制程序运行走向的方式.主要分为以下三种: 顺序结构:从上到下依次执行每条语句操作 ...
-
Java编程基础——运算符和进制
Java编程基础——运算符和进制 摘要:本文主要介绍运算符和进制的基本知识. 说明 分类 Java语言支持如下运算符: ◆ 算术运算符:++,--,+,-,*,/,%. ◆ 赋值运算符:=,+=,-= ...
-
Java编程基础——常量变量和数据类型
Java编程基础——常量变量和数据类型 摘要:本文介绍了Java编程语言的常量变量和数据类型. 常量变量 常量的定义 一块内存中的数据存储空间,里面的数据不可以更改. 变量的定义 一块内存中的数据存储 ...
-
Java编程基础——标识符和关键字
Java编程基础——标识符和关键字 摘要:本文主要介绍标识符和关键字. 标识符 是什么 Java语言中,为各种变量.方法.类和包等起的名字,统统称之为Java标识符. 命名规则 ◆ 应以字母.下划线. ...
随机推荐
-
运行impala tpch
1.安装git和下载tpc-h-impala脚步 [root@ip-172-31-34-31 ~]# yum install git [root@ip-172-31-34-31 ~]# git clo ...
-
使用curl命令获取文件下载速度
使用curl可以下载网络内容,那如何获取curl下载时的下载速度呢,使用下面的命令即可: # curl -Lo /dev/null -skw "%{speed_download}\n&quo ...
-
JVM学习笔记(三)------内存管理和垃圾回收
JVM内存组成结构 JVM栈由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制.堆被划分为新生代和旧生 ...
-
QT事件研究的文章
我始终认为,Windows里最重要的不是API,而是消息.同理,QT里最重要的是事件.然而我对事件的原理和用法至今不是很理解,先放几篇文章在这里,有空回来细细研读: http://m.blog.chi ...
-
mongDB
MongoDB[第一篇]MongodDB初识 NoSQL介绍 一.NoSQL简介 NoSQL,全称是”Not Only Sql”,指的是非关系型的数据库. 非关系型数据库主要有这些特点:非关系型的 ...
-
谈谈如何用eoLinker管理各类API接口及分享API接口管理小技巧教程
在前后端分离的开发模式下,前后端往往需要接口文档来进行交互.我的上一篇随笔中已经写到用传统的文档写接口时,由于需求经常变动,接口文档也会随之变动.一开始,某接口信息已经写入文档,但后期因为需求变动,发 ...
-
iPhone开发初探
本文是作者从一无所知到入门的知识学习过程,并结合自己在嵌入式开发的经验所写的技术总结文章,以供后来者学习. 苹果公司的iphone平台采用Object-c做为native language的开发,Ob ...
-
小程序 TabBar 定制
使用微信小程序开发时,用到了其 API - tabBar,设置如下(详细的内容可以参考官网 api): "tabBar": { "color": "# ...
-
linux上面是否有安装redis,redis启动
1.进入/usr/local/src目录,下载redis # cd /usr/local/src# wget http://download.redis.io/releases/redis-4.0.6 ...
-
001-windows下Elasticsearch安装、Elasticsearch-header安装
一.window安装Elasticsearch安装 elasticsearch的客户端版本必须与服务端版本主版本保持一致. 1.java安装[略] 2.elasticsearch下载 地址:https ...