当前位置 : 首页 » 文章分类 :  开发  »  Java-字符串

Java-字符串

[TOC]


String

java.lang.String

public final class String 
extends Object 
implements Serializable, Comparable<String>, CharSequence

String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现(所以字符串常量值上也是可以使用String类的成员方法的)。

字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。例如:

String str = "abc";

等效于:

char data[] = {'a', 'b', 'c'};
String str = new String(data);

下面给出了一些如何使用字符串的更多示例:

System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);

String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。大小写映射基于 Character 类指定的 Unicode 标准版。

Java 语言提供对字符串串联符号(”+”)以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。

除非另行说明,否则将 null 参数传递给此类中的构造方法或方法将抛出 NullPointerException。

String 表示一个 UTF-16 格式的字符串,其中的增补字符 由代理项对 表示(有关详细信息,请参阅 Character 类中的 Unicode 字符表示形式)。索引值是指 char 代码单元,因此增补字符在 String 中占用两个位置(无论中文英文,java中一个字符占2个字节)。

length()

int length()
字符串长度,无论字母、数字、汉字,长度都是1

charAt()

char charAt(int index)
返回指定索引处的 char 值。索引范围为从 0 到 length() - 1。序列的第一个 char 值位于索引 0 处,第二个位于索引 1 处,依此类推,这类似于数组索引。

substring(int beginIndex, int endIndex)

String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。

contains(CharSequence s)

public boolean contains(CharSequence s)
当且仅当此字符串包含指定的 char 值序列时,返回 true。

  • 参数:s - 要搜索的序列
  • 返回:如果此字符串包含 s,则返回 true,否则返回 false
  • 抛出: NullPointerException - 如果 s 为 null

indexOf()

int indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。返回的整数是 this.startsWith(str, k)为 true 的最小 k 值。
返回:如果字符串参数作为一个子字符串在此对象中出现,则返回第一个这种子字符串的第一个字符的索引;如果它不作为一个子字符串出现,则返回 -1。

endsWith()

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

join(CharSequence delimiter, CharSequence… elements)

public static String join(CharSequence delimiter, CharSequence... elements)
返回以指定分隔符连接的elements元素串联起来组成的String字符串
注意:如果某个元素为null,则”null”字符串会被加入。

  • 参数:
    • delimiter:分隔符
    • elements:要串接的元素
  • 抛出:NullPointerException:如果delimiter或elements为空
  • 从以下版本开始: 1.8

join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
返回以指定分隔符连接的elements元素串联起来组成的String字符串,例如:

List<String> strings = List.of("Java", "is", "cool");
String message = String.join(" ", strings);
//message returned is: "Java is cool"

Set<String> strings = new LinkedHashSet<>(List.of("Java", "is", "very", "cool"));
String message = String.join("-", strings);
//message returned is: "Java-is-very-cool"

注意:如果某个元素为null,则”null”字符串会被加入。

  • 参数:
    • delimiter:分隔符
    • elements:Iterable结构的要串接的元素集合
  • 抛出:NullPointerException:如果delimiter或elements为空
  • 从以下版本开始: 1.8

toLowerCase()

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

trim()

String trim()
返回此字符串移除了前导和尾部空白的副本;如果没有前导和尾部空白,则返回此字符串。

replaceAll()

String replaceAll(String regex, String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
例如 a.replaceAll(“ +”,” “);//将字符串a中的所有一个或多个连续空格替换为单个空格

split(String regex, int limit)

String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。
此方法返回的数组包含此字符串的子字符串,每个子字符串都由另一个匹配给定表达式的子字符串终止,或者由此字符串末尾终止。数组中的子字符串按它们在此字符串中出现的顺序排列。如果表达式不匹配输入的任何部分,那么所得数组只具有一个元素,即此字符串。

  • 参数:
    • regex:定界正则表达式
    • limit:结果阈值,如上所述
  • 返回:字符串数组,它是根据给定正则表达式的匹配拆分此字符串确定的
  • 抛出:PatternSyntaxException - 如果正则表达式的语法无效
  • 从以下版本开始: 1.4

limit 参数控制模式应用的次数,因此影响所得数组的长度。如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后一项将包含所有超出最后匹配的定界符的输入。如果 n 为非正,那么模式将被应用尽可能多的次数,而且数组可以是任何长度。如果 n 为 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。
例如:字符串 “boo:and:foo” 使用这些参数可生成以下结果:

Regex Limit 结果
: 2 { “boo”, “and:foo” }
: 5 { “boo”, “and”, “foo” }
: -2 { “boo”, “and”, “foo” }
o 5 { “b”, “”, “:and:f”, “”, “” }
o -2 { “b”, “”, “:and:f”, “”, “” }
o 0 { “b”, “”, “:and:f” }

调用此方法的 str.split(regex, n) 形式与以下表达式产生的结果完全相同:
Pattern.compile(regex).split(str, n)

注意转义字符.|

注意:“.”和“|”都是转义字符,必须得加”\\”。同理:*+也是如此
如果用“.”作为分隔的话,必须是如下写法:
String.split("\\."),这样才能正确的分隔开,不能用String.split(".")
如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“acountId=? and act_id =? or extra=?”,想and和or都做分隔符,可以用String.split(“and|or”);

split(String regex)

String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串。
该方法的作用就像是使用给定的表达式和限制参数 0 来调用两参数 split 方法。因此,所得数组中不包括结尾空字符串。

  • 参数:regex,定界正则表达式
  • 返回:字符串数组,它是根据给定正则表达式的匹配拆分此字符串确定的
  • 抛出:PatternSyntaxException - 如果正则表达式的语法无效
  • 从以下版本开始: 1.4

例如:字符串 “boo:and:foo” 使用这些表达式可生成以下结果:

Regex 结果
: { “boo”, “and”, “foo” }
o { “b”, “”, “:and:f” }

字符串拆分示例

拆分斜杠分隔字符串并存入列表

String orgcabinStr="W/C/Y/F";
String orgCabinArray[] = orgcabinStr.split("/");
List<String> orgCabinList = Arrays.asList(orgCabinArray);
int i=0;
while(i < orgCabinList.size() ){
    System.out.println(orgCabinArray[i++]);
}

equals()

boolean equals(Object anObject)
将此字符串与指定的对象比较。当且仅当该参数不为 null,并且是与此对象表示相同字符序列的 String 对象时,结果才为 true。

字符串相等判断

equals()方法比较的是对象的内容(区分字母的大小写格式) ,但是如果使用==双等号操作符比较两个对象时, 比较的是两个对象的内存地址, 所以它们不相等 (即使内容相同, 不同对象的内存地址也是不相同的)

equalsIgnoreCase()

boolean equalsIgnoreCase(String anotherString)
将此 String 与另一个 String 比较,不考虑大小写。如果两个字符串的长度相同,并且其中的相应字符都相等(忽略大小写),则认为这两个字符串是相等的。

isEmpty()

boolean isEmpty()
当且仅当 length() 为 0 时返回 true。
返回:如果 length() 为 0,则返回 true;否则返回 false。

字符串判空

以下是Java 判断字符串是否为空的四种方法:

  • 方法一: 最多人使用的一个方法, 直观, 方便, 但效率很低:
    if(s == null ||"".equals(s));
  • 方法二: 比较字符串长度, 效率高, 是我知道的最好一个方法:
    if(s == null || s.length() <= 0);
  • 方法三: Java SE 6.0 才开始提供的方法, 效率和方法二几乎相等, 但出于兼容性考虑, 推荐使用方法二.
    if(s == null || s.isEmpty());
  • 方法四: 这是一种比较直观,简便的方法,而且效率也非常的高,与方法二、三的效率差不多:
    if (s == null || s == "");
    注意:s == null 是有必要存在的。如果 String 类型为null, 而去进行 equals(String) 或 length() 等操作会抛出java.lang.NullPointerException. 并且s==null 的顺序必须出现在前面,不然同样会抛出java.lang.NullPointerException.
    如下Java代码会抛出空指针异常:
    String str = null;
    if(str.equals("") || str= == null){//会抛出异常
      System.out.println("success");
    }
    

StringBuffer

java.lang.StringBuffer

public final class StringBuffer 
extends Object 
implements Serializable, CharSequence

线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append(“le”) 会使字符串缓冲区包含“startle”,而 z.insert(4, “le”) 将更改字符串缓冲区,使之包含“starlet”。
通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。

只要发生有关源序列(如在源序列中添加或插入)的操作,该类就只在执行此操作的字符串缓冲区上而不是在源上实现同步。

每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。

String 的值是不可变的,每次对String的操作都会生成新的String对象,不仅效率低,而且耗费大量内存空间。
StringBuffer 默认分配16字节长度的缓冲区,当字符串超过该大小时,会自动增加缓冲区长度,而不是生成新的对象。
StringBuffer只能通过 new 来创建对象。
StringBuffer多用于需要对一个字符串进行频繁的修改,例如追加、插入、删除等。

reverse()

public StringBuffer reverse()
字符串逆置,设n为字符串长度,则新串中k位置的元素等于原串中n-k-1位置的元素

append()

StringBuffer append(String str)
将指定的 String 添加到此序列中。
按顺序将 String 参数中的字符添加到此 StringBuffer 中,并使 StringBuffer 在长度上增加该参数的长度。如果 str 为 null,则将 4 个 “null” 字符添加到此 StringBuffer 中。
假设执行 append 方法前的原有字符序列的长度为 n,则在添加后的新字符序列中,如果k小于n,则新字符序列中索引k处的字符等于原有字符序列中索引k处的字符;如果k大于n,则它等于参数str中索引 k-n 处的字符。
该方法在 this(目标)对象上实现同步,但不在源上(sb)实现同步。

deleteCharAt()

StringBuffer deleteCharAt(int index)
删除指定位置的字符

insert(int offset, String str)

StringBuffer insert(int offset, String str)
在指定位置插入字符串

setCharAt(int index, char ch)

void setCharAt(int index, char ch)
修改指定位置的字符


StringBuilder

java.lang.StringBuilder

public final class StringBuilder
extends Object 
implements Serializable, CharSequence

一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。

在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容为“start”的字符串生成器对象,则该方法调用 z.append(“le”) 将使字符串生成器包含“startle”,而 z.insert(4, “le”) 将更改字符串生成器,使之包含“starlet”。
通常,如果 sb 引用 StringBuilder 的实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。

每个字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区。如果内部缓冲区溢出,则此容量自动增大。

将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。

append()

StringBuilder append(String str)
将指定的 String 添加到此序列中。
按顺序将 String 参数中的字符添加到此 StringBuilder 中,并使 StringBuilder 在长度上增加该参数的长度。如果 str 为 null,则将 4 个 “null” 字符添加到此 StringBuilder 中。
假设执行 append 方法前的原有字符序列的长度为 n,则在添加后的新字符序列中,如果k小于n,则新字符序列中索引k处的字符等于原有字符序列中索引k处的字符;如果k大于n,则它等于参数str中索引 k-n 处的字符。

toString()

String toString()
转换为String类型


Pattern

java.util.regex.Pattern

public final class Pattern 
extends Object 
implements Serializable

正则表达式的编译表示形式。
指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。

因此,典型的调用顺序是:

Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();

在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。
语句boolean b = Pattern.matches("a*b", "aaaaab");
等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。

常用方法

matches()

static boolean matches(String regex, CharSequence input)
编译给定正则表达式并尝试将给定输入与其匹配。
例如:boolean b = Pattern.matches(“a*b”, “aaaaab”);
调用此便捷方法的形式Pattern.matches(regex, input);与表达式Pattern.compile(regex).matcher(input).matches() 的行为完全相同。

正则表达式构造

字符类

[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p(并集),等价于[a-dm-p]
[a-z&&[def]] d、e 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c(减去),等价于[ad-z]
[a-z&&[^m-p]] a 到 z,而非 m 到 p(减去),等价于[a-lq-z]

预定义字符类

. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字,等价于[0-9]
\D 非数字,等价于[^0-9]
\s 空白字符,等价于[ \t\n\x0B\f\r]
\S 非空白字符,等价于[^\s]
\w 单词字符,等价于[a-zA-Z_0-9]
\W 非单词字符,等价于[^\w]

边界匹配器

^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾

Greedy数量词

X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次

Logical运算符

XY X 后跟 Y
X|Y X 或 Y
(X) X,作为捕获组


总结

String,StringBuffer和StringBuilder

一般情况下,速度从快到慢为 StringBuilder > StringBuffer > String

  • 操作少量的数据使用 String;
  • 单线程操作大量数据使用 StringBuilder;
  • 多线程操作大量数据使用 StringBuffer。

StringBuffer与StringBuilder对比

StringBuffer类的方法是多线程安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。

StringBuffer与String对比

字符串的”+“操作实际上也是先创建一个StringBuffer对象,然后调用append()方法将字符串片段拼接起来,最后调用toString()方法转换为字符串。
对于长度较小的字符串,String的“+”操作更加直观,更具可读性,有些时候可以稍微牺牲一下效率。
但当在涉及大量字符串的频繁操作时,StringBuffer的效率优势会明显显现出来。

StringBuilder是否相等比较

StringBuilder与StringBuffer中没有覆盖Object的equals()方法,所以想要比较两个字符串是否相等,要将其转换为Strng类型。

字符串整型互相转换

字符串转整型

  • int Integer.parseInt(String s) 字符串转整型
  • Integer Integer.valueOf(String s) 字符串转Integer类

整型转字符串

  • String s = String.valueOf(i);
  • String s = Integer.toString(i);
  • String s = "" + i;

字符串串接符号+

Java 语言提供对字符串串联符号(”+”)以及将其他对象转换为字符串的特殊支持。
字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。
字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。
Java除了String重载了+之外,不支持其他操作符的重载。严格来说,+也不算运算符重载,只是JVM做的语法糖,因为其内部时通过StringBuilder的append方法实现的。


上一篇 Java-List

下一篇 Java-基础