【JavaSE】(8) String 类

一、String 类常用方法

1、构造方法

常用的这4种构造方法:直接法,或者传参字符串字面量、字符数组、字节数组。

JDK1.8 中,String 类的字符串实际存储在 char 数组中:

String 类也重写了 toString 方法,所以可以直接打印 String 类,打印效果就是字符串,而非 className@hashCode 的形式:

可以看到源码中,重写的 toString 直接返回的 this,因为 this 本身就是字符串类,println 会对 String 类进行处理,打印出字符串:

length() 方法 可以获取字符串长度,这区别于数组 通过属性 length 获取长度。

2、字符串的比较(包含字符串常量池)

在前面学习 equals 和 compareTo 方法时知道,直接使用**==** 比较,比较的是对象的地址,而非对象的内容:

但通过两种构造方式得到的 String 类,比较的结果却不同,它们存在区别:

  • 法1 :① 字符串常量池不存在 "hello"对象 >> 在常量池创建"hello"对象 >> 在堆上创建"hello"对象 >> 在栈上创建 s1 引用,存放堆上对象地址。② 字符串常量池存在"hello"对象 >> 直接在堆上创建"hello"对象 >> 在栈上创建 s2 引用,存放堆上对象地址。
  • 法2 :① 字符串常量池不存在 "hello"对象 >> 在常量池创建"hello"对象 >> 在栈上创建 s3 引用,存放常量池上对象地址。② 字符串常量池存在"hello"对象 >> 在栈上创建 s4 引用,存放常量池上对象地址。

因此,法1得到 false,法2得到 true。由此可见,将频繁使用的字符串存到字符串常量池 ,能够提高性能减少内存开销 。参考博客:深入理解Java字符串常量池 | 二哥的Java进阶之路

如果想将 new String("hello") 也存放到字符串常量池中,可手动地使用intern 方法

回到比较,如果想比较对象的内容,使用 equals 和 compareTo 方法。还有 equalsIgnoreCase 和 compareToIgnoreCase 方法,可忽略字母大小写:

3、字符串查找

查找失败时,除了 charAt 抛出异常,其它方法都是返回 -1。

4、字符串转换

(1) 整数、浮点数、布尔值、对象、数组 >> 字符串

(2)字符串 >> 整数、浮点数、数组

(3)大小写转换

(4)格式化转换

5、字符串替换

6、字符串拆分

注,正则表达式中:

  • *、+、| 有特殊含义,需要加上 "\\"。
  • \ 在 java 中要用 "\\" 表示,在正则表达式中也有特殊含义,最后为"\\\\"。
  • 正则表达式中,| 表示连字符,可连接多个分隔符。

7、字符串截取

8、字符串的不可变性

题外话:Java 中的引用就是 C语言指针的改版,存的是对象的地址,但是它更安全,因为只允许 = 和 . 操作(除了数组,还有[ ] 操作),所以简单又不易出错。

从 String 类的注释中可以看到,字符串是常量,它的值不可修改:

String 类的内容是怎么做到不可修改的呢?有人说是因为 final,但并不是:

修饰类的 final 表示 String 类不可继承;修饰 value 的 final 表示这个数组引用不可修改,并不是引用指向的内容不可修改。

value 引用指向的字符串内容不可修改的原因

  • value 数组由 private 修饰。
  • String 类没有向外部提供修改 value 指向的对象的方法。

字符串不可修改的缺点 :每次修改字符串其实是创建一个新的对象效率低

字符串不可修改的优点:

  • 多线程 中使用 String 类更安全。(线程以后学习)
  • 方便储存在常量池。如果常量池中的字符串可修改,则会造成多个引用的变化。
  • 方便将固定 hashCode 存储在哈希表中。(哈希表以后学习)

二、可修改的字符串(StringBuilder和StringBuffer)

  • String 不可修改字符串内容,而 StringBuilder 和 StringBuffer 可修改字符串内容。
  • StringBuilder 和 StringBuffer 的功能大致相同,最大的不同 是:StringBuffer 提供了 synchronized 操作,能够保证线程安全。(详情以后学习)

1、String 和 StringBuilder 的对比以及 append 方法

可以看到当需要频繁修改字符串时 ,使用 StringBuilder 的效率要高很多,因为它不需要频繁创建新的对象。每次 +=,都会将旧的 s 对象自动销毁,所以大的不是空间开销,而是创建对象的时间开销。

2、capacity 和 ensureCapacity

当用 StringBuilder 创建可修改的字符串对象时,实际会申请比初始化的字符串更大的空间capacity 方法就是获取实际的空间大小

当字符串容量不够时,StringBuilder 会自动扩容,有时为了防止频繁扩容造成时间开销的增加 ,会使用 ensureCapacity 提前手动设置 好比较大的字符串容量

三、String 类练习题

1、387. 字符串中的第一个唯一字符 - 力扣(LeetCode)

思路:统计每种字母的个数,找到第一个个数为 1 的字母。

java 复制代码
class Solution {

    public int firstUniqChar(String s) {
        int[] cnt = new int[256];
        // 统计每种字符个数
        for(int i = 0; i < s.length(); i++)
            cnt[s.charAt(i)]++;

        // 找到第一个唯一的字符
        for(int i = 0; i < s.length(); i++)
            if(cnt[s.charAt(i)] == 1)
                return i;
        
        // 未找到
        return -1;
    }
}

2、字符串最后一个单词的长度_牛客题霸_牛客网

思路:找到最后一个空格位置,根据空格位置裁剪出最后一个单词,获取长度。

java 复制代码
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String s = in.nextLine();
            int index = s.lastIndexOf(' '); // 找到最后一个空格
            String lastWord = s.substring(index + 1, s.length()); // 裁剪出最后一个单词
            System.out.println(lastWord.length());
        }
    }
}

3、125. 验证回文串 - 力扣(LeetCode)

思路:先大写转小写,前、后设置一个标记移动,跳过非字母数字字符,匹配。

java 复制代码
class Solution {
    // 判断小写字母和数字
    public boolean isValidChar(char ch) {
        if((ch >= 'a' && ch <='z') || (ch >= '0' && ch <= '9'))
            return true;
        else
            return false;
    }

    public boolean isPalindrome(String s) {
        // 大写转小写
        s = s.toLowerCase();
        int i = 0, j = s.length() - 1;
        // 前、后移动
        while(i < j){
            // 前、后跳过所有其它字符,直到遇到小写字母和数字停止
            while(!isValidChar(s.charAt(i)) && i < j) i++;
            while(!isValidChar(s.charAt(j)) && i < j) j--;
            // 存在不匹配,则否
            if(s.charAt(i) != s.charAt(j)) return false;
            // 匹配,则更新i、j
            i++;
            j--;
        }

        return true;
    }
}

四、补充 -- FittenCode 插件

它是一个AI功能,可以预测 你要写的代码 ,还能根据项目 的内容对它提问

相关推荐
ThisIsClark1 分钟前
【gopher的java学习笔记】Java中Mapper与Entity的关系详解
java·笔记·学习
C++小厨神44 分钟前
MATLAB语言的编程范式
开发语言·后端·golang
我想学LINUX1 小时前
【2024年华为OD机试】(C/D卷,200分)- 5G网络建设 (JavaScript&Java & Python&C/C++)
java·c语言·javascript·网络·python·5g·华为od
chengxuyuan666661 小时前
JAVA基础语句整理
java·开发语言·python
别人家的孩子3801 小时前
EE213 Lab2 hspice simulation R/C-V Characteristics
开发语言·python
Java知识技术分享1 小时前
SecureUtil.aes数据加密工具类
java·后端·intellij-idea
小丁爱养花1 小时前
Spring MVC:设置响应
java·开发语言·前端
神洛华2 小时前
Y3编辑器功能指引
java·数据库·编辑器
冯萦岚2 小时前
R语言的图形用户界面
开发语言·后端·golang
{⌐■_■}2 小时前
【GORM】事务,嵌套事务,保存点事务的使用,简单电商平台go案例
开发语言·jvm·后端·mysql·golang