古法编程java之String、StringBuffer、StringBuilder

String类的常用方法

equals // 区分大小写,判断内容是否相等
equalsIgnoreCase //忽略大小写的判断内容是否相等
length // 获取字符的个数,字符串的长度
indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
lastIndexOf //获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
substring //截取指定范围的子串
trim //去前后空格
charAt:获取某索引处的字符, 注意不能使用Str[index] 这种方式
toUpperCase // 字符串转大写
toLowerCase // 字符串转小写
concat // 拼接字符串
replace //替换字符串中的字符
split //分割字符串
compareTo //比较两个字符串的大小
toCharArray //转换成字符数组
format //格式字符串, %s 字符串 %c 字符 %d 整型 %.2f 浮点型
​

随用随查,其实最好每个都用一遍,但我为了效率,只读了一遍定义,后面用到再说

StringBuffer类

StringBuffer 也是一个容器。它的很多方法都和 String 相同,但与 String 最大的区别在于它是可变长度的。

  • String 类实际上保存的是字符串常量,内部的值不能修改。每次 String 类的更新,实际上就是在更改地址,效率较低。

    • private final byte[] value;
  • StringBuffer 保存的是字符串变量,里面的值可以更改。每次 StringBuffer 的更新,实际上是更新内容,并不用每次更新地址,效率较高。

    • byte[] value;

此外,StringBuffer还有如下要点

1. StringBuffer的直接父类是 AbstractStringBuilder
2. StringBuffer实现了 Serializable ,即StringBuffer的对象可以串行化
3. 在父类 AbstractStringBuilder 中有属性byte[] value,不是fianl的,可以修改
4. StringBuffer是个final类,不能被继承

StringBuffer的初始化、和String的相互转化

// 初始化
// 第一种方法,创造一个大小为 16 的 byte 数组
StringBuffer sb = new StringBuffer();
// 第二种方法,创造一个指定大小的 byte 数组
StringBuffer sb2 = new StringBuffer(100);
// 第三种方法,创造一个字符串对应的 byte 数组
StringBuffer sb3 = new StringBuffer("hello");
​
// String -> StringBuffer
// 方式1:使用构造器
String str = "hello";
StringBuffer sb4 = new StringBuffer(str);
// 方式2:使用append()
StringBuffer sb5 = new StringBuffer().append(str);
​
// StringBuffer -> String
// 方式1:使用toString()
String str2 = sb5.toString();
// 方式2:使用构造器
String str3 = new String(sb5);

StringBuffer的常用方法

  1. 增:append

  2. 删:delete(start, end)

  3. 改:replace(start, end, string)
    // 将 start 到 end 之间的内容替换掉,不含 end

  4. 查:indexOf
    // 查找子串在字符串中第1次出现的索引,如果找不到返回-1

  5. 插:insert

  6. 获取长度:length

小练习

第一题

String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb.length());
​
System.out.println(sb);
StringBuffer sb1 = new StringBuffer(str);
System.out.println(sb1);

答案:

4
null
空指针异常

解析:

这道题的解决方法是去读源码:StringBuffer 的 append 方法执行到最后,它会有一个检查。如果传进来的字符串是 null 的话,它会执行一个叫 appendNull 的方法。就是直接把 null 看作 "null"字符串,因此第一个输出是 4,第二个是 null
new StringBuffer(str)点进去看源码,会走到int length = str.length();这步,那就没得说了,对着 null 访问length方法,肯定会保空指针异常。

StringBuilder

基本介绍:

StringBuilder 是一个可变的字符序列。这个类提供一个和 StringBuffer 兼容的 API,但是不保证同步。

StringBuilder 不是线程安全的。这个类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单线程使用的时候。如果可能,单线程优先采用此类,它比 StringBuffer 速度要快。

StreamBuilder 上的主要方法是 append 和 insert。可以重载这些方法,使它们接受任意数据。

1. StringBuilder的直接父类是 AbstractStringBuilder
2. StringBuilder实现了 Serializable ,即StringBuilder的对象可以串行化
3. 在父类 AbstractStringBuilder 中有属性byte[] value,不是fianl的,可以修改
4. StringBuilder是个final类,不能被继承
5. StringBuilder 没有做互斥处理,但是最为高效,因此在单线程的场景下使用

对比

我们比较一下 String、StringBuffer 和 StringBuilder:

  1. StringBuilder 和 StringBuffer 非常类似,它们都代表可变的字符序列,而且方法也类似。

  2. String 是不可变的字符序列,效率低,但是复用率很高。

  3. StringBuffer 是可变的字符序列,它在增删上效率较高,而且它是线程安全的。

  4. StringBuilder 也是可变的字符序列,它的效率最高,但它的线程不安全。

  5. String 的使用注意说明:
    String s = “a” 本质是创建一个字符串,但如果 s += “b” 的话,它就会把原来的 “a” 字符串丢弃,产生一个新的字符串 “ab”。如果多次执行这些改变字符串内容的操作,会导致大量的文本串留在内存中,降低效率。如果这样的操作放到循环中,会极大地影响程序的性能。结论是:如果我们需要对字符串做大量的修改,就不要使用 String。

最终结论:

如果字符串存在大量的修改操作:

  1. 且是单线程,就使用 StringBuilder

  2. 或者是多线程,就使用 StringBuffer

假如字符串很少修改,且被多个对象引用,则使用 String

3 个赞

这篇是上一篇的续,所以比较短,参见古法编程java之包装类、Integer、String
其他笔记参见JAVA学习记录总贴

我去,好久远的事情了,感觉不写算法题的话,好像没有学习这些语法的场景了