String类 - 下篇

发布于:2023-01-13 ⋅ 阅读:(618) ⋅ 点赞:(0)


String 类下篇

String 类 - 上篇 链接

前言: 上篇我们学习了 Stirng类的一些常用方法, 外加初步了解了一下我们的字符串常量池, 本文 继上文,完成String类的剩下知识点 。

1.字符串的不可变性


相比大家都 听过, 字符串 是 不可变 的 , 那么String类 是为什么是不可变的呢?

在这里插入图片描述

在我们现在的 知识储备上我们可以 认为 String 是不可改变的,但实际上我们 可以通过反射 进行 改变,反射将在后面学到,所以我们现在就认为 String类是不可改变的。


既然我们知道了 字符串是不可改变的,那么我们要如何 去完成字符串的修改呢?

字符串的修改

这里先来看一段代码

在这里插入图片描述


这里我们就会产生 3 个对象 (注意: 这里没有算 String 类 中的 value 数组)

在这里插入图片描述


刚刚我们说过 我们的字符串是 不可 变的 ,我们并不能在原来的字符串上 进行修改, 只能重新生成 对象, 所以我们 要 尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。


针对 说 : String类是不能修改的,所有的修改都会创建新对象,效率非常低下


我们可 通过 代码来验证,这里 会涉及到 StringBuilder, StringBufferu , 正好将我们 接下要介绍的 这个两个 给 引出来

public static void main(String[] args) {
    // 通过 System 底下的方法计算 时间戳
        long start = System.currentTimeMillis();
        String s = "";
        for (int i = 0; i < 10000; ++i) {
            s += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");
        for (int i = 0; i < 10000; ++i) {
            sbf.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);

        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();
        for (int i = 0; i < 10000; ++i) {
            sbd.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }


补充: StringBuilderStringBufferu 通过 append 进行拼接 不会产生 额外 的对象, 是在原来的字符串上完成拼接。

所以 StringStringBuilderStringBufferu 的 区别,就是 Stirng 每次 通过 + 拼接, 会产生新的对象 , 这里我们上面 三个 拼接 1w次, 就会有明显 的 区别 。

在这里插入图片描述

运行 程序会明显的发现我们的 String 类 拼接的 时间 是 比 StringBuilder, StringBufferu 要慢的多 。


这里我们 就需要注意: 如果在循环 中拼接 字符串,我们 要尽量 不用使用 String , 尽量使用 StringBuilderStringBufferu


下面我们就来 学习 一下 StringBuilderStringBufferu

StringBuilder和StringBuffer


前引 :

在这里插入图片描述


刚刚说过, 通过String 拼接是非常慢的 为什么 慢 , 慢到哪里 呢 ?

这里我们就需要 观察一下 他的 汇编 ,

在这里插入图片描述


这里 我们 可以 通过 StringBuilder 还原 成 上面 String 拼接的 效果

在这里插入图片描述


这个代码 就与 String 拼接的 代码 是 等价的。


下面就来 改进 用一个 StringBuilder 来完成我们的任务 ,这样完成了我们的简化,少了频繁 new 对象的 过程。

在这里插入图片描述

下面就来对 讲一讲 StringBuilderStringBuffer 的 区别

StringBuilder 和 StringBuffer的区别

区别 StringBuilder StringBuffer
相同点 是 一个 类 能表达字符串 是一个类 能表达字符串
相同点 不能直接 赋值 不能直接赋值
不同点 线程不安全 线程安全的


图示: StringBuilder 和 StringBuffer 不能直接 赋值

在这里插入图片描述


这里我们就必须 new ,通过 构造方法,完成我们 的 赋值。

在这里插入图片描述

如果我们 通过 sout 直接打印 这两个对象是 能 成功的打印出 字符串的,这 是 为什么呢?

在这里插入图片描述


这里就与我们的线程安全 有关 , 这里我们 我们的 StringBuffer 是 线程安全的, 而 StringBuilder 是 线程不安全的, 啥是线程安全呢?

这里 暂且 提一嘴 , 后面学到线程的时候 详细讲解 , 这里 只要知道 这两个类那个是线程安全的 那个是线程 不安全的 就好。

这里就来简单举个例子 :

在这里插入图片描述

在这里插入图片描述


通过上面 队 StringBuilder 和 StringBuffer 的讲解, 下面就来看 个面试 题

String、StringBuffer、StringBuilder的区别

答案 :

1.String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

2.StringBuffer与StringBuilder大部分功能是相似的

3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作


最后 我们在来 完成几道 力扣 的 编程题 结束我们的 String类学习

String类 oj题


1.字符串中的第一个唯一字符 - 力扣(LeetCode)
在这里插入图片描述


2.字符串最后一个单词的长度_
在这里插入图片描述


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

在这里插入图片描述


本题就一个难点, 如何 将 不是 字母 字符和 数组字符的排序,这里我们就可以单独写一个方法来判断, 如果 是 在 a 和 z 之间,或 0 到 9 之间就满足我们的条件,返回 true , 不是 返回 false 让 此时的 left 或 right 改变即可, 最后比较。 如果相等left ++ 和 right–,如果 不相等返回 false 就不是 回文串。 这我们同样可以使用 String类自带的方法。 这里就不使用了, 思路是一样 的,可以 自行了解

class Solution {

    public static boolean isValidChar(char ch){
        if((ch >= 'a' && ch <= 'z')|| (ch >= '0' && ch <= '9')) {
            return true;
        }
        return false;
    }
    public boolean isPalindrome(String s) {
        s = s.toLowerCase();
        int left = 0;
        int right = s.length()-1;
        while(left < right){
            while(left < right && !isValidChar(s.charAt(left))){
                //此时说明不是 字母
                left++;
            }
            while(left < right && !isValidChar(s.charAt(right))){
                right--;
            }
            // 走到这里说明left 和 right 处 都是字母
            if(s.charAt(left) != s.charAt(right)){
                return false;
            }else {
                left++;
                right--;
            }
        }
        return true;
    }
}

在这里插入图片描述


使用 String类 自带的方法

class Solution {
    public boolean isPalindrome(String s) {
        int n = s.length();
        int left = 0;
        int right = n-1;
        while(left <= right) {
          while(left < right &&!Character.isLetterOrDigit(s.charAt(left))){
              left++;
          }
          while(left< right &&!Character.isLetterOrDigit(s.charAt(right))) {
              right--;
          }
          if(Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))){
              return false;
          }
          left++;
          right--;
        }
        return true;
    }
}


本文结束 , 下文 预告: 异常。


网站公告

今日签到

点亮在社区的每一天
去签到