字符串对象:String,StringBulilder,StringBuffer

概念

String从概念上来说就是Unicode字符序列,且Java没有内置的字符串类型,而是在Java类库中提供了一个预定义类String,每个用双引号括起来的字符串都是String类的一个实例。

子串

String类提供了一个substring可以从一个较大的字符串提取出一个子串,例如:

String str = "Hello";String s = str.substring(0,3); //Hel

substring的第一个参数是复制的起始位置(最小是0),第二个参数是复制的截止位置,复制长度为第二个参数减第一个参数得到的值。

拼接

1. Java允许使用+号拼接字符串

2. 当将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串,例如:​​​​​​

int age = 13;String rating ="PG" + age;

这种特性通常体现在输出语句中:

System.out.println("The answer is " + answer);

3. 如果需要把多个字符串放在一起,用一个界定符分隔,可以使用静态join方法:

String all = String.join("/","S","M","L","XL");// all is the string "S/M/L/XL"

字符串相等判断

可以使用equals方法检测两个字符串是否相等。对于表达式:

s.equals(t);

如果字符串s 与字符串t相等,则返回 true;否则,返回false。需要注意的是,s与t可以是字符串变量,也可以是字符串字面量。例如,以下表达式是合法的:

"Hello".equals(greeting);

要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase方法

"Hello".equalsIgnoreCase("hello");

一定不要使用-==运算符检测两个字符串是否相等!这个运算符只能够确定两个字符串是否存放在同一个位置上。当然,如果字符串在同一个位置上,它们必然相等。但是,完全有可能将内容相同的多个字符串副本放置在不同的位置上。

String greeting = "Hello"; // initialize greeting to a stringif (greeting =="Hello") ...//probably trueif(greeting.substring(0,3) == "Hel") ...//probably false

如果虚拟机始终将相同的字符串共享,就可以使用=运算符检测是否相等。但实际上只有字符串字面量是共享的,而+或substring等操作得到的字符串并不共享。因此,千万不要使用=运算符测试字符串的相等性,以免在程序中出现这种最糟糕的 bug,看起来这种bug就像随机产生的间歇性错误。

空串与Null串

空串""是长度为0的字符串。可以调用以下代码检查一个字符串是否为空:

if (str.length() == 0)

if (str.equals(""))

空串是一个Java对象,有自己的串长度(0)和内容(空)。不过,String变量还可以存放一个特殊的值,名为null,表示目前没有任何对象与该变量关联。要检查一个字符串是否为null,要使用以下条件:

if (str == null)

有时要检查一个字符串既不是null也不是空串,这种情况下就需要使用以下条件:

if (str != null && str.length() != 0)

首先要检查str不为null,如果在一个null值上调用方法,会出现错误。

码点与代码单元

Java字符串由char值序列组成。从3.3.3节已经看到,char数据类型是一个采用UTF-16编码表示Unicode码点的代码单元。最常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。

length方法将返回采用UTF-16编码表示给定字符串所需要的代码单元数量。例如:​​​​​​​

String greeting = "Hello";int n = greeting.length(); //is 5

要想得到实际的长度,即码点数量,可以调用:

int cpCount = greeting.codePointCount(0,greeting.length);

调用s.charAt(n)将返回位置n的代码单元,n介于0~s.length()-1之间。例如:​​​​​​​

char first = greeting.charAt(0); //first is "H"char last = greeting.length(); //last is 'o'

要想得到第i个码点,应该使用下列语句​​​​​​​

int index = greeting.offsetByCodePoint(0,i);int cp = greeting.codePointAt(index);

为什么会对代码单元如此大惊小怪?请考虑以下语句:

𝕆 is the set of octonions.

使用UTF-16编码表示字符𝕆(U+10546)需要两个代码单元。调用:

char ch = sentence.charAt(1);

返回的不是一个空格,而是的第二个代码单元。为了避免这个问题,不要使用char类型。这太底层了。

如果想要遍历一个字符串,并且依次查看每一个码点,可以使用下列语句:​​​​​​​

int cp = sentence.codePointAt(i);if (Character.isSupplementaryCodePoint(cp)) i += 2;else i ++;

可以使用下列语句实现反向遍历:i --;

if(Character.isSurrogate(sentence.charAt(i))) i --;int cp = sentence.codePointAt(i);

显然,这很麻烦。更容易的办法是使用codePoints方法,它会生成一个int值的“流”,每个int值对应一个码点。可以将它转换为一个数组,再完成遍历。

int[] codePoints = str.codePoints().toArray();

反之,要把一个码点数组转换为一个字符串,可以使用构造器(我们将在第4章详细讨论构造器和 new操作符)。

String str = new String(codePoints,0,codePoints.length);

StringAPI

char charAt(int index)//返回给定位置的代码单元。除非对底层的代码单元感兴趣,否则不需要调用这个方法。int codePointAt(int index)5int codePointAt(int index)//返回从给定位置开始的码点。int offsetByCodePoints(int startIndex, int cpCount)//返回从startIndex码点开始,cpCount个码点后的码点索引int compareTo(String other)//按照字典顺序,如果字符串位于other之前,返回一个负数;如果字符串位于other之后,返回一个正数;如果两个字符串相等,返回0。IntStream codePoints()//将这个字符串的码点作为一个流返回。调用toArray将它们放在一个数组中new String(int[] codePoints, int offset, int count)//用数组中从offset开始的count个码点构造一个字符串boolean empty()boolean blank()//如果字符串为空或者由空格组成,返回trueboolean equals(Object other)//如果字符串与other相等,返回trueboolean equalsIgnoreCase(String other)//如果字符串与other 相等(忽略大小写),返回trueboolean startWith(String prefix)boolean endsWith(String suffix)//如果字符串以prefix开头或以 suffix或结尾,则返回trueint indexOf(String str)int indexOf(String str, int fromIndex)int indexOf(int cp)int indexOf(int cp, int fromIndex)//返回与字符串str或码点cp匹配的第一个子串的开始位置。从索引0或fromIndex开始匹配。如果在原始字符串中不存在 str,则返回-1int lastIndexOf(String str)int lastIndexOf(String str, int fromIndex)int lastIndexOf(int cp)int lastIndexOf(int cp, int fromIndex)//返回与字符串 str或码点cp匹配的最后一个子串的开始位置。从原始字符串末尾或fromIndex 开始匹配int length()//返回字符串代码单元的个数。int codePointCount(int startIndex, int endIndex)//返回startIndex和 endIndex-1之间的码点个数。String replace(CharSequence oldString, CharSequence newString)//返回一个新字符串。这个字符串用newString代替原始字符串中所有的oldString。可以用String或StringBuilder对象作为CharSequence参数String substring(int beginIndex)String substring(int beginIndex, int endIndex)//返回一个新字符串。这个字符串包含原始字符串中从beginIndex到字符串末尾或endIndex-1的所有代码单元String toLowerCase()String toUpperCase()//返回一个新字符串。这个字符串将原始字符串中的大写字母改为小写,或者将原始字符串中的所有小写字母改成大写字母String trim()String strip()//返回一个新字符串。这个字符串将删除原始字符串头部和尾部小于等于U+0020的字符(trim)或空格(strip)String join(CharSequence delimiter, CharSequence... elements)//返回一个新字符串,用给定的定界符连接所有元素String repeat(int count)//返回一个字符串,将当前字符串重复count次

注意:在API注释中,有一些CharSequence类型的参数。这是一种接口类型,所有字符串都属于这个接口。现在只需要知道,当看到一个 CharSequence形参(parameter)时,完全可以传入 String类型的实参(argument)。

StringBuilder

有些时候,需要由较短的字符串构建字符串,例如,按键或来自文件中的单词。如果采用字符串拼接的方式来达到这个目的,效率会比较低。每次拼接字符串时,都会构建一个新的String对象,既耗时,又浪费空间。使用StringBuilder类就可以避免这个问题的发生。

如果需要用许多小段的字符串来构建一个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构建器:

StringBuilder builder = new StringBuilder();

当每次需要添加一部分内容时,就调用append 方法​​​​​​​

builder.append(ch); //appends a single characterbuilder.append(str); //appends a string

在字符串构建完成时就调用toString方法,将可以得到一个String对象,其中包含了构建器中的字符序列。

String completedString = builder.toString();

StringBuffer

StringBuilder类在Java 5中引入。这个类的前身是StringBuffer,它的效率稍有些低,但允许采用多线程的方式添加或删除字符。如果所有字符串编辑操作都在单个线程中执行(通常都是这样),则应该使用StringBuilder。这两个类的API是一样的。

StringBuilderAPI

StringBulder()//构造一个空的字符串构建器int length()//返回构建器或缓冲器中的代码单元数量StringBuilder append(String str)//追加一个字符串并返回thisStringBuilder append(char c)//追加一个代码单元并返回thisStringBuilder appendCodePoint(int cp)//追加一个码点,并将其转换为一个或两个代码单元并返回thisvoid setCharAt(int i, char c)//将第i个代码单元设置为cStringBuilder insert(int offset, String str)//在offset位置插入一个字符串并返回thisStringBuilder insert(int offset, char c)//在offset位置插人一个代码单元并返回 thisStringBuilder delete(int startIndex, int endIndex)//删除偏移量从 startIndex到endIndex-1的代码单元并返回thisString toString()//返回一个与构建器或缓冲器内容相同的字符串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值