• java的String类的常用API详解


    模块一:基本语法

    前言:字符串创建对象创建字符串对象,需要查看API中字符串的构造方法。提供了多种创建对象的方式。

    1、字符串创建

    (1) 直接写字符串字面值 String s5 = “abcd”;
    (2) 利用字节数组创建字符串对象
    byte[] bs = {97, 98, 99, 100}; //ASCII编码表
    String s1 = new String(bs);
    System.out.println(s1);
    打印结果:abcd
    (3) 利用字节数组的一部分创建字符串对象
    String s2 = new String(bs, 1, 2);
    System.out.println(s2);
    打印结果:bc
    (4)利用字符数组创建字符串对象
    char[] chs = {‘a’, ‘b’, ‘c’,‘d’};
    String s3 = new String(chs);
    System.out.println(s3);
    打印结果:abcd
    (5)利用字符数组的一部分创建字符串对象
    String s4 = new String(chs, 2, 2)
    System.out.println(s4);
    打印结果: cd

    2、两种字符串的区别

    (1)直接写的字符串字面值,在常量池中,它可以被复用

        String s1 = "abc"; //s1存储的值地址0x111
    	String s2 = "abc"; //s2复用s1的地址0x111
    	System.out.println(s1 == s2); //true
    
    • 1
    • 2
    • 3

    (2)使用构造方法创建字符串对象,在堆内存中,每次创建对象都有新的地址值

    String s1 = new String("abc"); //s1存储的地址是0x222
    String s2 = new String("abc"); //s2存储的地址是0x333
    System.out.println(s1 == s2); //false
    
    • 1
    • 2
    • 3

    3、String类方法总结

    字符串有很多方法,需要根据需求找到合适的方法进行使用就可以了。 为了更加方便的记忆这些方法,建议对方法进行分类记忆。
    判断功能

    判断字符串的内容是否相等,不忽略大小写
    public boolean equals(Object str)
    判断字符串是否相等,忽略大小写
    public boolean equalsIgnoreCase(String anotherString)
    举例:“HELLO” 和 “hello” 是否相等
    判断字符串是否包含某些内容
    public boolean contains(CharSequence s)
    举例:“helloworld” 是否包含 “world”
    判断字符串以什么后缀结尾
    public boolean endsWith(String suffix)
    举例:“helloworld.java” 是否以 "java"结尾 public boolean
    判断字符串以什么前缀开头
    startsWith(String prefix)
    举例:“helloworld.java” 是否以 "hello"结开头

    获取功能

    获取字符串中某一个索引位置的字符
    public char charAt(int index) 
    获取字符串的长度 
    public int length()
    
    • 1
    • 2
    • 3
    • 4

    转换功能

    将此字符串转换为一个新的字符数组。
    public char[] toCharArray()
    将字符串转换为小写字母
    public String toLowerCase()
    将字符串转换为大写字母
    public String toUpperCase()
    把字符串转换为字节数组
    public byte[] getBytes()

    截取和替换功能
    截取字符串的一部分,从指定的索引位置开始一直到末尾

    public String substring(int beginIndex)
    截取字符串的一部分,从指定的开始位置一直到指定的结束位置(注意:包含头,不包含尾)
    public String substring(int beginIndex, int endIndex)
    使用新的字符串替换旧的字符串
    public String replaceAll(String regex, String replacement)

    切割功能

    使用指定的字符串开切割字符串,得到一个字符串数组
     public String[] split(String regex)
    注意:如果想要用"."进行切割,必须使用"\\."
    
    • 1
    • 2
    • 3

    StringBuilder类的方法
    构造方法

    public StringBuilder()
    构造一个不带任何字符的字符串容器,其初始容量为 16 个字符。
    【注意:容量不够用时,会自动扩容】

    public StringBuilder(String str)
    构造一个字符串容器,并初始化为指定的字符串内容。

    常用方法

    往字符串缓冲区(容器),添加任意类型的数据。
    public StringBuilder append(任意类型 i)  
    获取字符串缓冲区(容器)中,字符的个数
     public int length()  
      把字符串缓冲区(容器)中内容反转
     public StringBuilder reverse()  
     把字符串缓冲区(容器),转换为字符串
    public String toString()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    StringJoiner类的方法

    (1) 创建一个StringJoiner对象,用指定的分隔符
    构造方法 public StringJoiner(String s)

    (2) 创建一个StringJoiner对象,用指定的分隔符, 开始符号,结束符号
    public StringJoiner(String s,String start, String end)

    常用方法
    往字符串缓冲区(容器),添加字符串数据。
    public StringJoiner add(String i)
    获取字符串缓冲区(容器)中,字符的个数
    public int length()
    把字符串缓冲区(容器),转换为字符串
    public String toString()

    模块二:应用

    1、字符串切割演示
    String str = “www itcast cn”;
    //使用 “ ” 进行切割
    String[] array = str.split(" ");

    for (int i = 0; i < array.length; i++) {
    System.out.println(array[i]);
    }
    2、替换字符串中内容
    String str = “我的手机号码是:1234345566,有事联系我”;
    //替换字符串中的"1234345566" 为 “"
    String s = str.replaceAll(“1234345566”, "
    ”);
    System.out.println(s);
    3、比较字符串相等

    String s1 = “abc”; //s2复用s1的地址0x111
    String s2 = new String(“abc”); //s2存储的地址是0x333
    System.out.println(s1 == s2); //false,比较地址
    System.out.println(s1.equals(s2)); //true,比较内容
    原因:String类重写了Object类equals方法,所以使用String类的equals方法时比较的是两个字符串的内容。

    4、字符串遍历
    直接遍历字符串

    String str = "abcdefg";
    //快捷键:str.length().fori
    //str.length(): 获取str字符串的长度
    for(int i=0; i<str.length(); i++){
        //获取i索引位置的字符
        char ch = str.charAt(i);
        System.out.println(ch);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    把字符串转换为字符数组,再遍历数组

    String str = "abcdefg";
    //把字符串转换为字符数组
    char[] chs = str.toCharArray();
    //遍历字符数组
    for(int i=0; i< chs.length; i++){
        char ch = chs[i];
        System.out.println(ch);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5、字符串拼接的练习
    (1)使用StringBuilder, 把一个数组元素拼接成一个字符串

    int[] array = {1,2,3,4,5};
    StringBuilder sb = new StringBuilder("{"); 
    //遍历数组, 把元素拼接成一个字符串
    for(int i=0; i<array.length; i++){
        //判断是否为最后一个元素
        if(i == array.length-1){
           sb.append(array[i]); //如果是最后一个元素,不用拼接“,”
        }else{
    	   sb.append(array[i]).append(",");//如果不是最后一个元素,需要用拼接“,”
        }
    }
    sb.append("}");
    //把StringBuilder转换为字符串
    String result = sb.toString();
    System.out.println(result);  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    (2)使用StringJoiner, 把一个数组元素拼接成一个字符串

    int[] array = {1,2,3,4,5};
    StringJoiner sj = new StringJoiner(",", "[","]");
    //遍历数组, 把元素拼接成一个字符串
    for(int i=0; i<array.length; i++){
        //array[i]+""  目的是把数组的元素转换为字符串
        sj.add(array[i]+"");
    }
    //把StringBuilder转换为字符串
    String result = sj.toString();
    System.out.println(result);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    模块二:经典面试题

    1、 String 属于基础的数据类型吗?

    String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。

    2、String str="i"与 String str=new String(“i”)一样吗?

    不一样,因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

    3、说说你理解的字符串的不变性

    字符串的不可变性是指通过 String的方法来修改字符串都会产出新的字符串,但并非指字符串的字符一定无法被修改,我们可以通过反射一样可以对字符串的“状态/值” 进行修改。
    另外字符串对象是不可变的。因为这样可以保证多个引用可以同时指向字符串池中的同一个对象。如果字符串是可变的,那么一个引用操作改变了对象的值,对其他引用会有影响,这样显然是不合理的。

    4、String 是线程安全的吗?

    String是不可变类,一旦创建了String对象,我们就无法改变它的值。因此,它是线程安全的,同一个字符串实例可以被多个线程共享,保证了多线程的安全性。

    5、在使用 HashMap 的时候,用 String 做 key 有什么好处?

    HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,而因为字符串是不可变的,当创建字符串时,它的hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。

    6、String、StringBuffer、StringBuilder的区别与联系
    当面试官问到这个问题时,可以从以下3个方面来回答:

    (1) 首先从速度上来说
    StringBuilder>StringBuffer>String。
    接下来解释为什么String速度最慢。因为String是内容不可变的,它的底层使用了一个不可变的数组private final char value[];因此不能用来拼接字符串; 而StringBuffer和StringBuilder都是内容可变的。底层使用的是可变的字符数组char[] value;(没有使用final来修饰)。可以用来拼接字符串。
    (2)从线程安全来说
    因为String是不可被继承的,所以不可改变,故是线程安全的;StringBuffer是线程安全的;StringBuilder是线程不安全的。
    (3) 适用场景
    String适用于少量字符串操作的情况;
    StringBuffer适用于多线程下大量字符串操作的场景;
    StringBuilder适用于单线程下大量字符串操作的场景。

    八、String、StringBuffer、StringBuilder三者的对比

    • String:不可变的字符序列;底层使用final char[]存储
    • StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
    • StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
    
    (1).StringBuffer与StringBuilder的内存解析
    以StringBuffer为例:
    String str = new String();//char[] value = new char[0];
    String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};
     
    StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。
    System.out.println(sb1.length());//
    sb1.append('a');//value[0] = 'a';
    sb1.append('b');//value[1] = 'b';
     
    StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];
    //问题1. System.out.println(sb2.length());//3
    //问题2. 扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
    默认情况下,扩容为原来容量的2+ 2,同时将原数组中的元素复制到新的数组中。
    指导意义:开发中建议大家使用:StringBuffer(int capacity)StringBuilder(int capacity)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.对比String、StringBuffer、StringBuilder三者的执行效率
    从高到低排列:StringBuilder > StringBuffer > String

    4.StringBuffer、StringBuilder中的常用方法
    增:append(xxx)
    删:delete(int start,int end)
    改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
    查:charAt(int n )
    插:insert(int offset, xxx)
    长度:length();
    *遍历:for() + charAt() / toString()

    7、如何将字符串反转?
    使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
    示例代码:

    1)StringBuffer的reverse方法
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer. append("abcdefg");
    System. out. println(stringBuffer. reverse()); // gfedcba2)StringBuilder的reverse方法
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder. append("abcdefg");
    System. out. println(stringBuilder. reverse()); // gfedcba
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    8、 (1) 题型1

    String s1 = “abc”; String s2 = “a” + “b” + “c”;
    //在编译时期,把 “a”+“b”+"c"转换为 “abc”
    System.out.println(s1 == s2);
    打印结果:true
    (2) 题型2
    String s3 = “a”;
    String s4 = “bc”; String s5 = “abc”;
    System.out.println((s3 + s4) == s5);
    打印结果:false
    结论:(s3+s4)是变量相加,会生成新的字符串

    9、字符串拼接

    public static void main(String[] args) {
        String str = "helloWorld";
        String str1 = "hello" + "World";
        System.out.println("str == str1:" + (str == str1));//true
        
        String hello = "hello";
        String world = "World";
        String helloWorld = hello + world;
        System.out.println("str == helloWorld:" + (str == helloWorld));//false
        
        String helloWorld1 = hello + "World";
        System.out.println("str == helloWorld1:" + (str == helloWorld1));//false
        
        String strConcat = hello.concat(world); //底层源码:用了new,创建了新对象
        System.out.println("str == strConcat:" + (str == strConcat));//false	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    说明:

    • 字符串相加时如果含有字符串变量,则先在堆中开空间,再拼接,本质是 new StringBuilder 对象进行 append 操作,拼接后调用 toString() 返回 String 对象。
    • 字符串相加时不含字符串变量,是先加,然后在常量池找。如果有就直接返回,否则,就在常量池中创建一个字符串常量,不会用到 StringBuilder。
  • 相关阅读:
    Python安装第三方库
    软件项目管理 7.4.2.进度计划编排-关键路径法
    LaTeX之一:macos上latex环境搭建(homebrew安装+vscode配置+ MacTex)和B站视频、网站、教程等相关资料推荐(Overleaf、公式预览网站)
    基于springboot+Vue的学生实践管理平台开发
    【代码精读】optee的线程向量表
    ddns-go配合aliyun域名解析通过ipv6实现共享桌面
    Rust 模块系统
    spark
    嵌入式软件开发常用的3种架构
    IO进程及相关函数
  • 原文地址:https://blog.csdn.net/CNCDXX_88/article/details/127844745