String

一、创建string对象

  1. 字符串的字符使用Unicode编码,一个字符占两个字节
  2. 常用构造器:
  1. String s1 = new String();
  2. String s2 = new String(String original);
  3. String s3 = new String(char[] a);
  4. String s4 = new String(char[] a,int startIndex,int count);
  5. String s5 = new String(byte[] b);

QQ截图20220304113755.png

  1. String类实现了接口Serializable,String可以串行化,在网络中传输;
    实现了接口Comparable,String对象可以比大小
  2. String是final类,不能被其他的类继承
    String源码:有属性private final char value[]; 用于存放字符串内容
    value是一个final类型,不可以修改,即不能指向新的地址,但单个字符可以改变
  3. 创建String对象的两种方式
    • 直接赋值 String s = “saa”;
    • 调用构造器 String s = new String(“aaaa”);
    • 区别
      • 直接赋值先从常量池查看是否有”saa”数据空间,如果有,直接指向;如果没有,则重新创建,然后指向。s最终指向的是常量池的空间地址

未命名文件-16464664328531.png

  1. - 先在堆中创建空间,里面维护value属性,指向常量池的"aaaa"空间,如果没有,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址

未命名文件 (1).png

  1. 字符串是不可变的,一个字符串对象一旦被分配,其内容是不可改变的
    String s1 = “hello”;
    s1 = “hhh”;

aa.png

  1. String + 优化,判断创建的常量池对象,是否有引用指向
    String a = “hello”+”abc” <=> String a = “helloabc” 只创建了一个对象
  2. String a = “hello”;
    String b = “hhh”;
    String c = a + b;
    综上,常量相加,是在常量池中,变量相加,是在堆中
    1. 先创建一个StringBuilder sb = StringBuilder()
    2. 执行 sb.append(“hello”)
    3. sb.append(“hhh”)
    4. String c = sb.toString() 这个方法中new了一个对象

c实际指向堆中的对象,堆中的对象指向池中的”hellohhh”

综上,常量相加,是在常量池中,变量相加,是在堆中

二、方法

String类保存字符串常量,每次更新都需要重新开辟空间,效率低

  1. public class String01 {
  2. public static void main(String[] args) {
  3. // 1. equals 比较内容是否相同(区分大小写)
  4. String str1 = "hello";
  5. String str2 = "Hello";
  6. System.out.println(str1.equals(str2)); // false
  7. // 2. equalsIgnoreCase 忽略大小写判断内容是否相等
  8. System.out.println(str1.equalsIgnoreCase(str2)); // true
  9. // 3. length 获取字符的个数,字符串的长度
  10. System.out.println(str1.length()); // 5
  11. // 4. indexOf获取字符在字符串对象中第一次出现的索引,从0开始,找不到,返回-1
  12. System.out.println(str1.indexOf('e')); // 1
  13. // 5. lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从 0 开始,如果找不到,返回-1
  14. System.out.println(str1.lastIndexOf('l')); // 3
  15. System.out.println(str1.lastIndexOf("ll")); // 2
  16. // 6. subString 截取指定范围字符串
  17. System.out.println(str1.substring(2)); // llo 索引2开始后面的
  18. System.out.println(str1.substring(1,3)); // el 从索引1开始截取,截取到索引3-1 = 2位置
  19. // 7. toUpperCase 转换成大写
  20. System.out.println(str2.toUpperCase()); //HELLO
  21. // 8. toLowerCase 转换成小写
  22. System.out.println(str2.toLowerCase()); // hello
  23. // 9. concat 拼接字符串
  24. System.out.println(str1.concat("aaa").concat("2333")); // helloaaa2333
  25. // 10. replace 替换字符串中的字符
  26. System.out.println(str1.replace("ll","qq") +" "+ str1); // heqqo
  27. System.out.println(str1); // hello replace返回的结果是替换过的
  28. // 11. split 分割字符串
  29. String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";
  30. String[] split = poem.split(","); // 按,分割
  31. String path = "C:\\aaa\\vvv";
  32. split = path.split("\\\\");
  33. // 12. toCharArray转换成字符数组
  34. char[] chars = str1.toCharArray();
  35. for (int i = 0; i < chars.length; i++) {
  36. System.out.println(chars[i]);
  37. }
  38. // 13. compareTo 比较两个字符串的大小,前者大返回正数,后者大返回负数,相等返回0
  39. /*
  40. (1) 长度相同,并且每个字符也相同,返回0
  41. (2) 长度相同或者不同,但在进行比较时,可以区分大小 c1-c2
  42. (3) 前面的部分都相同,返回str1.len-str2.len
  43. public int compareTo(String anotherString) {
  44. int len1 = value.length;
  45. int len2 = anotherString.value.length;
  46. int lim = Math.min(len1, len2);
  47. char v1[] = value;
  48. char v2[] = anotherString.value;
  49. int k = 0;
  50. while (k < lim) {
  51. char c1 = v1[k];
  52. char c2 = v2[k];
  53. if (c1 != c2) {
  54. return c1 - c2;
  55. }
  56. k++;
  57. }
  58. return len1 - len2;
  59. }
  60. */
  61. String a = "abc";
  62. String b = "adc";
  63. System.out.println(a.compareTo(b));
  64. // 14. format格式字符串 占位符 %s %d %.2f %c
  65. String name = "lll";
  66. int age = 20;
  67. double score = 98.3;
  68. char g = '是';
  69. String formatStr = "我的姓名是%s 年龄是%d,成绩是%.2f 是%c";
  70. String info = String.format(formatStr,name,age,score,g);
  71. System.out.println(info); // 我的姓名是lll 年龄是20,成绩是98.30 是是
  72. }
  73. }

三、StringBuffer类

  1. 基本介绍
    StringBuffer代表可变的字符序列,可以对字符串内容进行增删,是一个容器
    StringBuffer是final类,实现了Serializable,可以串行化,继承了抽象类AbstractStringBuilder,有属性char[] value,在堆中,不是final
    StringBuffer字符内容是存在char[] value,在增加或删除时不用每次更换地址,创建新的对象,效率高于String

ss.png

  1. StringBuffer stringBuffer = new StringBuffer("hello");
  1. 和String相互转换

    1. public class StringAndStringBuffer {
    2. public static void main(String[] args) {
    3. // String->StringBuffer
    4. String str = "hello world";
    5. // 方式1 构造器 返回的是StringBuffer对象,对str本身没有影响
    6. StringBuffer stringBuffer = new StringBuffer(str);
    7. // 方式2 append方法
    8. StringBuffer stringBuffer1 = new StringBuffer();
    9. stringBuffer1 = stringBuffer1.append(str);
    10. // StringBuffer->String
    11. StringBuffer stringBuffer2 = new StringBuffer("hello");
    12. // 方式1 使用StringBuffer提供的toString方法
    13. String s = stringBuffer2.toString();
    14. // 方式2 使用构造器
    15. String s1 = new String(stringBuffer2);
    16. }
    17. }
  2. StringBuffer类常见方法

    1. public class StringBufferMethod {
    2. public static void main(String[] args) {
    3. StringBuffer s = new StringBuffer("hello");
    4. // 增
    5. s.append(','); // hello,
    6. s.append("world"); // hello,world
    7. s.append(100).append(true).append(15.23); // hlelo,world100true15.23
    8. // 删
    9. // 删除索引为>=start <end处的字符
    10. s.delete(11, 14); // hello,worldtrue15.23 删除[11,14)的字符
    11. // 改
    12. s.replace(9, 11, "改的"); // hello,wor改的true15.23 替换索引[9,11)的字符
    13. // 查找指定的子串在字符串第一次出现的索引,找不到返回-1
    14. int indexOf = s.indexOf("改的");
    15. System.out.println(indexOf); // 9
    16. // 插入
    17. s.insert(9,"插入"); // 在索引9位置插入,原来索引为9内容自动后移
    18. System.out.println(s); // hello,wor插入改的true15.23
    19. // 长度
    20. System.out.println(s.length()); // 22
    21. }
    22. }

四、StringBuilder类

  1. 基本介绍

可变的字符序列,提供一个与StringBuffer兼容的API,但不保证线程安全,用在字符串缓冲区被单个线程使用的时候,大多数情况比StringBuilder快

主要是append和insert方法,可以重载以接受任意类型的数据

  1. 常用方法

StringBuilder是final类,实现了Serializable,可以序列化,继承了抽象类AbstractStringBuilder,有属性char[] value

  1. StringBuilder stringBuilder = new StringBuilder();

五、String、StringBuffer 和 StringBuilder 的比较

效率:StringBuilder > StringBuffer > String

如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder

如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder

如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer

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