Java学习笔记:String、StringBuilder与StringBuffer

String类是Java内置的用来表示字符串的类,所有的字面量字符串,都是String类的实例实现。当然,我们也可以通过new一个新对象的方式,创建一个String实例。

java 复制代码
public class App {  
    public static void main(String[] args) {  
        // 方式1:使用字面量  
        String s1 = "hello";  
        // 方式2:new  
        String s2 = new String("hi");  
    }  
}

需要注意的是,使用字面量创建的字符串,字符串会存储到内存的字符串常量池中。在Java有所谓"享元模式"(共享元素),即两个变量如果引用相同的字符串内容,系统会指向同一个字符串常量池中内的字符串。证明如下:

java 复制代码
public class Demo0 {  
    public static void main(String[] args) {  
        // 用字面量创建一个String对象  
        String s1 = "hello";  
        // 用字面量创建另外一个String对象,字符串内容完全相同  
        String s2 = "hello";  
        // 证明两个变量都是同一个对象的引用  
        System.out.println(s1 == s2); //  true  
    }  
}

而如果不是用的字面量,是用new创建两个String对象,则是完全不同的结果。用new创建两个字符串内容完全相同的String对象,会在内存堆里存储对象。两个变量则是完全不同的对象。证明如下:

java 复制代码
public class Demo1 {  
    public static void main(String[] args) {  
        // 用new创建一个String对象  
        String s1 = new String("hello");  
        // 用new创建另外一个String对象,字符串内容完全相同  
        String s2 = new String("hello");  
        // 证明两个变量是两个对象  
        System.out.println(s1 == s2); //  false  
    }  
}

字符串在编程中,是最常见的几种对象,因此String方法非常非常丰富。String对象是不可变的,其方法产生的字符串,都是返回一个新的String对象。

String常用的方法

String类的常见方法可以划分为基本操作、转换操作、替换与去除、截取与分隔、判断操作等分类。

String类的基本操作方法有:获取字符串长度、返回字符在字符串中第一次、最后一次出现的索引、返回字符串索引上的字符等。

java 复制代码
public class Demo2 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 获取字符串的长度  
        System.out.println(s1.length()); // 5  
        // 返回字符在字符串中第一次出现的索引  
        System.out.println(s1.indexOf('l')); // 2 (索引从0开始)  
        // 返回字符在字符串中最后一次出现的索引  
        System.out.println(s1.lastIndexOf('l')); // 3  
        // 返回指定索引的字符  
        System.out.println(s1.charAt(1)); // e  
    }  
}

String类的转换操作有:将字符串转换为字符数组、将int类型转换为字符串、将字符串中所有字符转换为小写、将字符串中所有字符转换为大写

java 复制代码
public class Demo3 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 将字符串转换为字符数组  
        char[] chs = s1.toCharArray();  
        for (int i = 0; i < chs.length; i++) {  
            System.out.print(chs[i]); // hello  
        }  
        System.out.println();  
        // 将int类型转换为字符串  
        int a = 10086;  
        String s2 = String.valueOf(a);  
        System.out.println(s2); // 10086  
        // 将字符串中的字符全部转换为大写  
        String s3 = s1.toUpperCase();  
        System.out.println(s3); // HELLO  
        // 将字符串中的字符全部转换为小写  
        String s4 = s1.toLowerCase();  
        System.out.println(s4); // hello  
    }  
}

String类的替换去除操作:用新字符串替换原有字符串,得到一个新的字符串;去除字符串首尾的空格。

java 复制代码
public class Demo4 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 用新字符串替换原有字符串,得到一个新的字符串  
        String s2 = s1.replace("hello", "helloworld");  
        System.out.println(s2); // helloworld  
        // 去除字符串首尾的空格  
        String s3 = "  hello  ";  
        String s4 = s3.trim();  // 建议用strip()替代
        System.out.println(s4); // hello  
    }  
}

需要注意:trim()只能去除ASCII码≤32 的空白字符(空格、制表符、换行等),但不能去除全角空格或其他Unicode空白字符。Java 11+引入了strip()方法来解决这个问题。因此,建议使用strip()方法替代trim()方法

String类的截取与分隔操作有:根据参数将原字符串分隔为若干个字符串(字符串数组)、截取从指定索引后的所有字符、截取从指定开始索引到指定结束索引之间的字符。

java 复制代码
public class Demo5 {  
    public static void main(String[] args) {  
        String s1 = "this is a text";  
        // 将原字符串分隔为若干个字符串(字符串数组)  
        String[] arr = s1.split(" ");  
        for (int i = 0; i < arr.length; i++) {  
            System.out.println(arr[i]);  
        }  
        // 截取从指定索引后的所有字符  
        String s2 = "helloworld";  
        System.out.println(s2.substring(5)); // world  
        // 截取从指定开始索引到指定结束索引之间的字符  
        System.out.println(s2.substring(2, 4)); // ll  
    }  
}

String类的判断操作有:判断与指定字符串比较是否相等、判断字符串是否以指定字符串开始、判断字符串是否以指定字符串结尾、判断字符串是否包含指定的字符序列、判断字符串是否为空(字符串长度为0)。

java 复制代码
public class Demo6 {  
    public static void main(String[] args) {  
        String s1 = "hello";  
        // 判断与指定字符串比较是否相等  
        System.out.println(s1.equals("hello")); // true  
        // 判断字符串是否以指定字符串开始  
        System.out.println(s1.startsWith("he")); // true  
        // 判断字符串是否以指定字符串结尾  
        System.out.println(s1.endsWith("lo")); // true  
        // 判断字符串是否包含指定的字符序列  
        System.out.println(s1.contains("llo")); // true  
        // 判断字符串是否为空  
        System.out.println(s1.isEmpty()); // false  
    }  
}

StringBuilder和StringBuffer类

由于String对象是不可变对象,因此String类的所有方法若是返回字符串,都是返回一个新的字符串。由于字符串是高频出现的对象,而因为字符串的不可变特性,对内存的开销较大。

因此,Java系统前后推出了StringBuffer类和StringBuilder类,作为String类的补充。两者都是可变的字符串对象,两者的方法都几乎相同,都是在原字符串上进行变更修改,而不是产生一个新的字符串对象。

以StringBuilder为例,演示StringBuilder和StringBuffer类的常用方法。

java 复制代码
public class Demo7 {  
    public static void main(String[] args) {  
        StringBuffer str = new StringBuffer("hello");  
        // append方法:添加字符串  
        str.append(" world");  
        System.out.println(str); // hello world  
        // insert方法:在指定位置添加字符串  
        str.insert(5, " java's");  
        System.out.println(str); // hello java's world  
        // replace方法:替换字符串  
        str.replace(5, 12, " java");  
        System.out.println(str); // hello java world  
        // delete方法:删除字符串  
        str.delete(5, 10);  
        System.out.println(str); // hello world  
    }  
}

StringBuffer类和StringBuilder类区别在于相对运行快慢和线程安全性,StringBuffer是线程安全的,运行性能比StringBuilder慢。而StringBuilder虽然是线程不安全的,但是优势在于运行速度快。

java 复制代码
package string.demo2;  
  
public class Demo7 {  
    public static void main(String[] args) {  
        StringBuffer str0 = new StringBuffer("hello");  
        StringBuilder str1 = new StringBuilder("hello");  
  
        // 测试StringBuffer对象方法的运行时间  
        long start = System.nanoTime();  
        // append方法:添加字符串  
        str0.append(" world");  
        System.out.println(str0); // hello world  
        // insert方法:在指定位置添加字符串  
        str0.insert(5, " java's");  
        System.out.println(str0); // hello java's world  
        // replace方法:替换字符串  
        str0.replace(5, 12, " java");  
        System.out.println(str0); // hello java world  
        // delete方法:删除字符串  
        str0.delete(5, 10);  
        System.out.println(str0); // hello world  
        long end = System.nanoTime();  
        System.out.println("StringBuffer运行时间:" + (end - start) + "纳秒");  
  
        System.out.println("------------------------------------------------");  
  
        // 测试StringBuilder对象方法的运行时间  
        long start1 = System.nanoTime();  
        str1.append(" world");  
        System.out.println(str1);  
        str1.insert(5, " java's");  
        System.out.println(str1);  
        str1.replace(5, 12, " java");  
        System.out.println(str1);  
        str1.delete(5, 10);  
        System.out.println(str1);  
        long end1 = System.nanoTime();  
        System.out.println("StringBuilder运行时间:" + (end1 - start1) + "纳秒");  
    }  
}
shell 复制代码
hello world
hello java's world
hello java world
hello world
StringBuffer运行时间:398609纳秒
------------------------------------------------
hello world
hello java's world
hello java world
hello world
StringBuilder运行时间:92160纳秒

进程已结束,退出代码为 0

由此可见,StringBuilder确实要更快一些。一般情况下,我们都是单线程运行程序,因此推荐用StringBuilder。

相关推荐
重生之后端学习19 小时前
19. 删除链表的倒数第 N 个结点
java·数据结构·算法·leetcode·职场和发展
qq_124987075319 小时前
基于小程序中医食谱推荐系统的设计(源码+论文+部署+安装)
java·spring boot·后端·微信小程序·小程序·毕业设计·计算机毕业设计
Coder_Boy_19 小时前
基于SpringAI的在线考试系统-阅卷评分模块时序图
java·人工智能·spring boot
sycmancia19 小时前
C语言学习07——变量的作用域
c语言·学习
linweidong19 小时前
C++大型系统中如何组织头文件和依赖树?
java·c++·架构
橘子师兄19 小时前
C++AI大模型接入SDK—环境搭建
开发语言·c++·人工智能
lkbhua莱克瓦2419 小时前
JavaScript核心语法
开发语言·前端·javascript·笔记·html·ecmascript·javaweb
SmartBrain19 小时前
Agent 知识总结
服务器·数据库·笔记
bubiyoushang88819 小时前
基于MATLAB的近红外光谱与PLS方法测定药片有效成分含量的实现
开发语言·matlab
鹿角片ljp19 小时前
力扣14.最长公共前缀-纵向扫描法
java·算法·leetcode