字符串的使用
- 一、String类
- 构造String对象
- 字符串的合并
- String 类的常用方法
- 1. 字符串长度:`public int length()`
- 2. 字符串比较:`public boolean equeals(Object anObject)`
- 3. 前缀比较:`public boolean startsWith(String prefix)`、后缀比较:`public boolean endsWith(String suffix)`
- 4. 字典序大小比较:`public int compareTo(String anotherString)`
- 5. 是否包含字符串:`public boolean contains(String s)`
- 6. 字符串第一次出现的索引位置:`public int indexOf(String s)`、字符串最后一次出现的索引位置:`public int lastIndexOf(String str)`
- 7. 字符串截取:`public String substring(int beginIndex)`
- 8. 字符替换:`public String replace(char oldChar, char newChar)`
- 9. 字符序列分解:`public String[] split(String regex)`
- 10. 前后空格清除:`public String trim()`
- 字符串与基本数据类型的相互转化
- 字符串与字符数组、字节数组
- 二、StringBuffer类
- StringBuffer类的构造方法
- StringBuffer类的常用方法
- 1. 字符串追加:`public AbstractStringBuilder append(String str)`
- 2. 字符串插入:`public AbstractStringBuilder insert(int offset, String str)`
- 3. 删除指定位置的字符串:`public synchronized StringBuffer delete(int start, int end)`
- 4. 替换指定位置的字符串:`public synchronized StringBuffer replace(int start, int end, String str)`
- 5. 翻转当前字符串:`public synchronized StringBuffer reverse()`
- 补充
- String类和StringBuffer、StringBuilder类的区别和使用场景
一、String类
在程序设计中经常需要进行字符序列的处理,因此Java中提供了专门用于处理字符序列的的String类。String类为final类,即String类不能被扩展,拥有子类。
String类中使用private final char value[];
进行字符存储,这意味着String对象中存储的字符不能变动,或者说每次字符变动都意味着创建新了的String对象。
构造String对象
String类可以直接使用双引号括起的字符序列进行赋值,如String s = "hello"
。这样赋值的字符序列会被存入堆内存中的字符串常量池,s
是存放在栈内存中的字符串对象,用于存放字符串实体"hello"
的地址引用。如果有两个String对象被赋予了相同的字符序列,这两个对象将引用同一个实体。
String 类也可以使用 new
运算符先分配内存空间并在内存空间中放入字符序列,然后计算出引用(凡是使用new
运算符构建出的对象都不存放在常量池中)。
String s1 = "hello"; // 存放 "hello" 于常量池。
String s2 = "hello"; // 常量池中已存在"hello",直接引用。
/* s3中的字符序列是通过char数组申请空间,与s1和s2不同 */
char[] array = {'h', 'e', 'l', 'l', 'o'};
String s3 = new String(array);
System.out.println(s1 == s2); // 引用相同,结果为true。
System.out.println(s1 == s3); // 引用不同,结果为false。
System.out.println(s1.equals(s3)); // 字符序列相同,结果为true。
字符串常量池:其中的数据在编译时就已经确定,程序运行期间不允许改变。
字符串比较:使用
equals
方法进行字符串比较、使用==
进行引用比较。
字符串的合并
String对象可以使用 +
运算符进行合并。需要注意的是,如果进行合并的两个对象有一个是变量,则合并的结果也是变量(等同于使用new
运算符)。
String s1 = "a";
String s2 = "ab";
String s3 = "a" + "b";
String s4 = s1 + "b"; // 相当于 new String(s1 + "b");
System.out.println(s2 == s3); // 结果为 true,引用相同
System.out.println(s2 == s4); // 结果为 false
System.out.println(s2.equals(s4)); // 结果为 true
String 类的常用方法
1. 字符串长度:public int length()
此方法返回字符串长度。
2. 字符串比较:public boolean equeals(Object anObject)
该方法重写了Object中的equeals方法。当参数中的对象是字符串类型时,与其中的字符序列进行比较,若相同返回 true,不同返回 false。当参数不是字符串类型,直接返回false。
类似方法:
- 忽视大小写的字符比较:
public boolean equalsIgnoreCase(String anotherString)
3. 前缀比较:public boolean startsWith(String prefix)
、后缀比较:public boolean endsWith(String suffix)
判断当前字符序列的前缀或者后缀是否是参数中的String对象的字符序列。若是则返回 true,不是则返回 false。
重载方法:
- 偏移起始位置的前缀比较(无视前面的偏移长度个字符,如偏移 1 就无视第一个字符):
public boolean startsWith(String prefix, int toffset)
4. 字典序大小比较:public int compareTo(String anotherString)
按字典序与参数中的String对象的字符序列进行比较,若大于则返回正数,若小于则返回负数,相等则返回 0。
类似的方法还包括:
- 忽略大小写的字典序大小比较:
public int compareToIgnoreCase(String str)
。 - 将序列按字典序大小进行排序:java.util 包中Arrays类的
sort()
方法。
5. 是否包含字符串:public boolean contains(String s)
若包含参数中的String对象的字符序列则返回true,否则返回false。
这个方法的实现是直接调用了
indexOf()
方法。
6. 字符串第一次出现的索引位置:public int indexOf(String s)
、字符串最后一次出现的索引位置:public int lastIndexOf(String str)
返回包含参数中的String对象的字符串第一次或最后一次出现的索引位置;若没有出现,则返回-1。
重载方法:
- 获取指定字符第一次出现的索引:
public int indexOf(int ch)
;获取指定字符最后一次出现的索引:public int lastIndexOf(int ch)
。 - 指定起点获取指定字符第一次出现的索引:
public int indexOf(int ch, int fromIndex)
;指定终点获取指定字符最后一次出现的索引:public int lastIndexOf(int ch, int endIndex)
。 - 指定起点获取指定字符串第一次出现的索引:
public int indexOf(String str, int fromIndex)
;指定终点获取指定字符串最后一次出现的索引:public int indexOf(iString str, int endIndex)
。
7. 字符串截取:public String substring(int beginIndex)
这个方法会返回一个新的String对象,是复制了原String对象从 beginIndex 位置开始到 length - 1 位置的字符的得到的。
重载方法:
- 指定终点的字符串截取:
public String substring(int beginIndex, int endIndex)
类似方法:
- 获取指定索引的 char 字符:
public char charAt(int index)
。
8. 字符替换:public String replace(char oldChar, char newChar)
这个方法会返回一个新的String对象,将原字符串中的所有oldChar替换为newChar。
重载方法:
- 字符串替换:
public String replace(CharSequence otarget, CharSequence replacement)
。
类似方法:
- 带正则表达式的字符串替换:
public String replaceAll(String regex, String replacement)
- 带正则表达式且只替换一次的字符串替换:
public String replaceFirst(String regex, String replacement)
正则表达式是一种特殊的字符序列,这种序列中包含具有特殊意义的元字符。String对象可以通过
public boolean matches(String regex)
方法判断当前的字符串是否和regex
对象中的正则表达式匹配。对于正则表达式的详细规则可以参考菜鸟教程或者直接查看java.util.regex包中的Pattern类。
也可以利用在线正则工具测试表达式是否正确。
9. 字符序列分解:public String[] split(String regex)
该方法返回一个String数组,使用参数指定的正则表达式 regex 作为分隔标记分解当前的String的字符序列,并将分解出的结果放在String数组中。
Java还提供了StringTokenizer类专门分解String对象,该类是出于兼容性考虑而保留的遗留类,Java并不鼓励使用这个类,但这个类分解字符串的速度比split方法略快。
10. 前后空格清除:public String trim()
这个方法会返回一个新的String对象,是对当前字符串序列去掉首尾空格的字符序列。
字符串与基本数据类型的相互转化
- 字符串转基本类型,所有的基本类型的包装类都提供了将字符串转化为对应基本类型的类方法。
public static boolean parseBoolean(String s) throws NumberFormatException;
public static byte parseByte(String s) throws NumberFormatException;
public static short parseShort(String s) throws NumberFormatException;
public static int parseInt(String s) throws NumberFormatException;
public static long parseLong(String s) throws NumberFormatException;
public static float parseFloat(String s) throws NumberFormatException;
public static Double parseDouble(String s) throws NumberFormatException;
对于整型的部分基本类型,还可以使用
int radix
参数设定基数(进制)。
- 基本类型转字符串,所有类都是Object类的子类或间接子类,
Object类中有一个public String toString()
方法,所有基本类型的包装类中都已经重写了该方法,可以直接通过该方法将基本类型转换为字符串; 同时,String 类也提供了类方法valueOf用于将基本类型转换为字符串:
public static String valueOf(boolean b);
public static String valueOf(int i);
public static String valueOf(char c);
public static String valueOf(long l);
public static String valueOf(float f);
public static String valueOf(double d);
对于没有重写 toString 方法的引用类型,调用 toString 方法得到的结果为:
包名.类名@对象的引用的字符串表示
(这里的类名是引用的实体的类名)
字符串与字符数组、字节数组
1. 字符串与字符数组
String类内部使用字符数组存储字符,可以使用字符数组构造String对象:
/* 方法1:将整个数组存入字符串 */
String(char[] value);
/* 方法2:设定偏移量和长度 */
String(char[] value, int offset, int count);
并且String也提供了将String对象的字符序列存放到数组中的方法:
/* 方法1:将字符串中的所有字符存入一个数组中 */
public char[] toCharArray();
/*
* 方法2:将字符串中的部分字符复制到数组中
*
* @param srcBegin 复制字符串中第一个字符的索引
* @param srcEnd 复制字符中最后一个字符的索引
* @param dst 目标数组
* @param dstBegin 目标数组的起始偏移量
*/
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin);
因为char字符可以进行整数的运算,所有可以利用char的特性对字符串进行加密。
2. 字符串与字节数组
也可以使用byte数组构造String对象,与char数组不同的是,byte数组会根据编码方式转码为char数组:
/* 方法1:使用平台默认编码存入整个数组 */
String(byte[]);
/* 方法2:指定起始位置、长度和编码字符集的名字*/
String(byte[], int offset, int length, String charsetName);
/* 方法3:指定起始位置、长度和编码字符集 */
String(byte[], int offset, int length, Charset charset);
/* 举例 */
byte[] bytes = new byte[]{-28, -67, -96, -27, -91, -67};
System.out.println(new String(bytes, StandardCharsets.UTF_8) ); // 输出:"你好"(UTF-8中每个汉字占用三个字节)
与构造方法相对应,也可以将字符串转为字节数组:
/* 方法1:使用平台默认编码转换 */
public byte[] getBytes();
/* 方法2:根据字符集名字转换 */
public byte[] getBytes(charsetName);
/* 方法3:根据字符集转换 */
public byte[] getBytes(charsetName, Charset charset);
二、StringBuffer类
String类因为某些原因设计为了不可变(每次改变实际上创建新对象),这种特性导致了在修改字符串时开销较大,因此Java还提供了StringBuffer类,StringBuffer类的对象的实体的内存空间可以自动的改变大小,便于存放一个可变的字符序列。
StringBuffer类的构造方法
StringBuffer()
:默认给对象分配一个容量为16的实体,当实体容量不足时,实体容量自动增加一倍(新建数组并复制)。StringBuffer(int size)
:通过size参数指定容量大小。StringBuffer(String s)
:分配容量为参数s的长度再加16。
StringBuffer类的常用方法
1. 字符串追加:public AbstractStringBuilder append(String str)
将参数str中的字符串追加到当前 StringBuffer 对象中,并返回当前对象的引用。
方法重载:
- 所有类型的字符追加:
public AbstractStringBuilder append(任意类型参数)
,所有类型都会被转为字符串类型追加到当前 StringBuffer 对象中。 - 带偏移量和长度的字符追加:
public AbstractStringBuilder append(char str[], int offset, int len)
。
2. 字符串插入:public AbstractStringBuilder insert(int offset, String str)
将参数str中的字符串插入到offset参数的指定的索引上,并返回当前对象的引用。
字符串插入与字符串追加具有相似的重载方法。
3. 删除指定位置的字符串:public synchronized StringBuffer delete(int start, int end)
从当前StringBuffer对象中删除指定子序列,子序列下标由 start 到 end,并返回当前对象的引用。
类似方法:
- 删除指定位置的字符:
public synchronized StringBuffer deleteCharAt(int index)
。
4. 替换指定位置的字符串:public synchronized StringBuffer replace(int start, int end, String str)
从当前StringBuffer对象中替换指定子序列为参数str中的字符序列,子序列下标由 start 到 end,并返回当前对象的引用。
5. 翻转当前字符串:public synchronized StringBuffer reverse()
翻转当前字符串,并返回当前对象的引用。
补充
StringBuffer类方法的使用
可以注意到,StringBuffer类的方法在大部分情况下都返回了当前对象的引用,这样的设计使得StringBuffer对象可以连续调用方法,例如:
String s1 = "hello";
String s2 = "Java";
StringBuffer sb = new StringBuffer();
sb.append(s1).append(' ').append(s2); // 连续调用方法
StringBuilder类
StringBuilder类和StringBuffer类具有相同的父类AbstractStringBuilder,因此他们具有几乎相同的方法。区别在于StringBuffer类是线程安全的,但效率相对较低;而StringBuilder类是线程不安全的,效率相对较高。
在实际使用中,StringBuilder的性能提升并不明显,因此在会使用线程的情况下,尽量使用StringBuffer来保证安全。
String类和StringBuffer、StringBuilder类的区别和使用场景
- 区别:String类的值不可变,StringBuffer、StringBuilder类的的值是可变的。String类、StringBuffer类是线程安全的;StringBuilder类是线程不安全的。
- 使用场景:对于只进行少量字符操作的场景使用String类;在单线程需要进行大量字符串操作的情况下使用StringBuilder;在多线程进行大量字符操作的情况下使用StringBuffer类。