当前位置: 首页 > article >正文

【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 的字母。

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、字符串最后一个单词的长度_牛客题霸_牛客网

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

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)

 

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

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功能,可以预测你要写的代码,还能根据项目的内容对它提问


http://www.kler.cn/a/514749.html

相关文章:

  • 风光并网对电网电能质量影响的matlab/simulink仿真建模
  • Spring MVC和Spring WebFlux的区别
  • 可替代CentOS 7的Linux操作系统选型
  • 前端【7】javascript-dom操作
  • 基于微信小程序高校订餐系统的设计与开发ssm+论文源码调试讲解
  • 编译chromium笔记
  • 计算机怎么入门
  • 动态规划(DP)(细致讲解+例题分析)
  • ChatGPT接入苹果全家桶:开启智能新时代
  • HBased的原理
  • HDBaseT和KVM 和POE是怎么融合在一块的
  • 国产编辑器EverEdit - 文件列表
  • 08-Elasticsearch
  • 区块链的数学基础:核心原理与应用解析
  • ImportError: cannot import name ‘datapoints‘ from ‘torchvision‘
  • # [Unity]【游戏开发】 脚本生命周期与常见事件方法
  • 局域网中 Windows 与 Mac 互相远程连接的最佳方案
  • 网络编程-网络原理HTTP初识
  • 【Python】笔试面试题之生成器、闭包、字典
  • Java设计模式 九 桥接模式 (Bridge Pattern)
  • 【软件测试项目实战 】淘宝网:商品购买功能测试
  • Spring Boot 使用 Micrometer 集成 Prometheus 监控 Java 应用性能
  • R 语言科研绘图 --- 散点图-汇总
  • C++:将字符数组rkpryyrag,每个字母转换为其前面第13个字母后输出,如果超过a则从z再继续接着数。例如:b前面第1个字母是a。a前面第3个字母是x。
  • 【华为路由的arp配置】
  • 利用 SoybeanAdmin 实现前后端分离的企业级管理系统