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

java后端开发day16--字符串(二)

在这里插入图片描述
(以下内容全部来自上述课程)

1.StringBuilder

因为StringBuilder是Java已经写好的类。
java在底层对他进行了一些特殊处理。
打印对象不是地址值而是属性值。

1.概述

StringBuilder可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串操作的效率。

2.构造方法

  • public StringBuilder() 创建一个空白可变字符串的对象,不含有任何内容
  • public StringBuilder(String str) 根据字符串的内容,来创建可变字符串对象

3.成员方法

  • public StringBuilder append(任意类型) 添加数据,并返回对象本身
  • public StringBuilder reverse() 反转容器中的内容
  • public int length() 返回长度(字符出现的个数)
  • public String toString() 通过toString()就可以实现把StringBuilder转换成String
package StringBuilder;

public class StringBuilderDemo1{
    public static void main(String[] args) {
        //1.创建对象
        StringBuilder sb = new StringBuilder("abc"); //abc

        //2.添加元素
        sb.append(1);
        sb.append(2.3);
        sb.append(true); //abc12.3true

        //3.反转
        sb.reverse();  //eurt3.21cba

        //4.长度
        int len = sb.length();
        System.out.println(len);  //11

        //5.把StringBuilder变回字符串
        String str = sb.toString();
        System.out.println(str);  //eurt3.21cba

        //System.out.println(sb);
    }
}

4.链式编程

当我们在调用一个方法的时候,不需要用变量接受他的结果,可以继续调用其他的方法。
举个例子(格式不完全):

int len = getString().substring(1).replace("A","Q").length();
System.out.println(len);   //2

public ststic String getString(){
	Scanner sc = new Scanner(System.in);
	System.out.println("请输入一个字符串");
	String str = sc.next();
	return str;   //abc
}

5.简化代码

初始:

sb.append("aaa");
sb.append("bbb");
sb.append("ccc");
sb.append("ddd");

简化后:

sb.append("aaa").append("bbb").append("ccc").append("ddd");

小总结:使用StringBuilder的场景:

  1. 字符串的拼接
  2. 字符串的反转

2.StringJoiner

1.概述

StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。
JDK8出现的。

2.构造方法

  • public StringJoiner(间隔符号) 创建一个StringJoiner对象,指定拼接时的间隔符号。
  • public StringJoiner(间隔符号,开始符号,结束符号) 创建一个StringJoiner对象,指定拼接式的三个符号。

3.成员方法

  • public StringJoiner add(添加的内容) 添加数据,并返回对象本身
  • public int length() 返回长度(字符出现的个数)
  • public String toString() 返回一个字符串(该字符串就是拼接之后的结果)
package sj;

import java.util.StringJoiner;

public class StringJoinerDemo {
    public static void main(String[] args) {
        //1.创建对象
        StringJoiner sj = new StringJoiner(",","[","]");
        //2.添加元素
        sj.add("hello");
        sj.add("world");
        sj.add("java");
        int len = sj.length();
        System.out.println("len:"+len); //18:字符个数

        //3.打印结果
        System.out.println(sj); //[hello,world,java]

        String str = sj.toString();
        System.out.println(str);  //[hello,world,java]
    }
}

3.字符串原理

1.字符串存储的内存原理

  • 直接赋值会服用字符串常量池中的
  • new出来的不会复用,而是开辟一个新的空间

2.==号比较的到底是什么?

  • 基本数据类型比较数据值
  • 引用数据类型比较地址值

3.字符串拼接的底层原理

1.等号右边没有变量

拼接的时候没有变量,都是字符串。
触发字符串的优化机制。
在编译的时候就已经是最终的结果了,
复用串池中的字符串。
在这里插入图片描述

2.等号右边有变量

JDK8以前底层会使用StringBuilder:
系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接。
拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象。

JDK8版本:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。

小拓展:想查看任何类(String Builder)的源码可以在IDEA里用快捷键ctrl+N
继续查找相关的继承成员(toString)可以用快捷键ctrl+F12
在这里插入图片描述
结论:如果有很多字符串变量进行拼接,不要直接+。在底层会创建多个对象,浪费时间,浪费性能。

4.StringBuilder提高效率原理图

StringBuilder是一个内容可变的容器。
在这里插入图片描述

5.StringBuilder源码分析

默认创建一个长度为16的字节数组。
添加的内容长度小于16,直接存。
添加的内容大于16会扩容(原来的容量*2+2)
如果扩容之后还不够,以实际长度为准。

快捷键:ctrl+alt+t 快速生成循环代码

4.练习

1.转换罗马数字

键盘录入一个字符串
要求1:长度为小于等于9
要求2:只能是数字
将内容变成罗马数字
下面是阿拉伯数字跟罗马数字的对比关系:
I->1,II->2,III->3,IV->4,V->5,VI->6,VII->7,VIII->8,IX->9
注意点:
罗马数字里面是没有0的,
如果键盘录入的数字包含0,可以变成" "(长度为0的字符串)

方法1(数组):

package String;

import java.util.Scanner;

public class Test1 {

	public static void main(String[] args) {
	/*  键盘录入一个字符串
        要求1:长度为小于等于9
        要求2:只能是数字
        将内容变成罗马数字
        下面是阿拉伯数字跟罗马数字的对比关系:
        I->1,II->2,III->3,IV->4,V->5,VI->6,VII->7,VIII->8,IX->9
        注意点:
        罗马数字里面是没有0的,
        如果键盘录入的数字包含0,可以变成" "(长度为0的字符串)*/

        //1.键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        while(true){
            System.out.println("请输入一个字符串:");
            //2.判断是否符合要求
            boolean flag = checkStr(str);
            if(flag){
            	break;
            } else {
            	System.out.println("当前字符串不符合要求,请重新录入");
                continue;
            }
        }

        //3.将内容变成罗马数字
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            int number = c - 48;  //字符0~9对应的数字是48~57
            String s = toRomanNumerals(number);
            sb.append(s);
        }
        System.out.println(sb);
	}
    public static String toRomanNumerals(int number){
        //1.定义一个字符串数组,用来存储罗马数字
        String[] arr = {" ","I","II","III","IV","V","VI","VII","VIII","IX"};
        return arr[number];
    }



    public static boolean checkStr(String str){
        //1.长度是否小于等于9
        if(str.length() > 9){
        	return false;
        }
        //2.只能是数字
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            if(c < '0' || c > '9'){
                return false;
            }
        }
        return true;
    }
}


方法2(switch):

package String;

import java.util.Scanner;

public class Test1Case2 {
    public static void main(String[] args) {
    /*  键盘录入一个字符串
        要求1:长度为小于等于9
        要求2:只能是数字
        将内容变成罗马数字
        下面是阿拉伯数字跟罗马数字的对比关系:
        I->1,II->2,III->3,IV->4,V->5,VI->6,VII->7,VIII->8,IX->9
        注意点:
        罗马数字里面是没有0的,
        如果键盘录入的数字包含0,可以变成" "(长度为0的字符串)*/

        //1.键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        while(true){
            System.out.println("请输入一个字符串:");
            //2.判断是否符合要求
            boolean flag = checkStr(str);
            if(flag){
                break;
            } else {
                System.out.println("当前字符串不符合要求,请重新录入");
                continue;
            }
        }
        //3.将内容变成罗马数字
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            String s = changeLuoMa(c);
            sb.append(s);
        }
        System.out.println(sb);

    }
    public static String changeLuoMa(char number){
        String str =switch (number){
            case '1'-> "I";
            case '2'->"II";
            case '3'-> "III";
            case '4'-> "IV";
            case '5'-> "V";
            case '6'-> "VI";
            case '7'-> "VII";
            case '8'-> "VIII";
            case '9'-> "IX";
            default-> " ";
        };
        return str;
    }


    public static boolean checkStr(String str){
        //1.长度是否小于等于9
        if(str.length() > 9){
            return false;
        }
        //2.只能是数字
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            if(c < '0' || c > '9'){
                return false;
            }
        }
        return true;
    }
}

2.调整字符串的内容并比较

给定两个字符串,A和B。
A的旋转操作就是将A最左边的字符移动到最右边。
例如,若A=‘abcde’,在移动一次之后结果就是’bcdea’。
如果在若干次调整操作之后,A能变成B,那么返回True。
如果不能匹配成功,则返回false。

方法1(截取):

package String;



public class Test2 {
    public static void main(String[] args) {
        /*给定两个字符串,A和B。
        A的旋转操作就是将A最左边的字符移动到最右边。
        例如,若A='abcde',在移动一次之后结果就是'bcdea'。
        如果在若干次调整操作之后,A能变成B,那么返回True。
        如果不能匹配成功,则返回false。*/

        //1.定义两个字符串
        String A = "abcde";
        String B = "cdeab";

        //2.旋转字符串
        String rotateStr = rotateString(A);
        System.out.println(rotateStr);

        //3.旋转并进行比较
        boolean flag = compare(A,B);

        //4.输出结果
        System.out.println(flag);

    }
    public static boolean compare(String A,String B){
        for(int i = 0; i < A.length(); i++){
            A = rotateString(A);
            if(A.equals(B)){
                return true;
            }
        }
        return false;
    }







    //作用:旋转字符串,把最左边的字符移动到最右边
    //形参:旋转前的字符串
    //返回值:旋转后的字符串
    public static String rotateString(String str){
        //套路:
        //如果我们看到要修改字符串的内容
        //可以有两种办法:
        //1.用substring进行截取,把左边的字符截取出来拼接到右边
        //2.把字符串变成字符数组,然后把字符数组中的元素进行位置交换,最后再把字符数组变成字符串

        //第一种:截取思路
        //获取最左边的字符
        char c = str.charAt(0);
        //获取剩余的字符
        String left = str.substring(1);
        //把左边的字符拼接到右边
        String result = left + c;
        return result;
    }

}

方法2(数组):

package String;



public class Test2Case2 {
    public static void main(String[] args) {
        /*给定两个字符串,A和B。
        A的旋转操作就是将A最左边的字符移动到最右边。
        例如,若A='abcde',在移动一次之后结果就是'bcdea'。
        如果在若干次调整操作之后,A能变成B,那么返回True。
        如果不能匹配成功,则返回false。*/

        //1.定义两个字符串
        String A = "abcde";
        String B = "cdeab";

        //2.旋转字符串
        String rotateStr = rotateString(A);
        System.out.println(rotateStr);

        //3.旋转并进行比较
        boolean flag = compare(A,B);

        //4.输出结果
        System.out.println(flag);

    }
    public static boolean compare(String A,String B){
        for(int i = 0; i < A.length(); i++){
            A = rotateString(A);
            if(A.equals(B)){
                return true;
            }
        }
        return false;
    }







    //作用:旋转字符串,把最左边的字符移动到最右边
    //形参:旋转前的字符串
    //返回值:旋转后的字符串
    public static String rotateString(String str){
        //套路:
        //如果我们看到要修改字符串的内容
        //可以有两种办法:
        //1.用substring进行截取,把左边的字符截取出来拼接到右边
        //2.把字符串变成字符数组,然后把字符数组中的元素进行位置交换,最后再把字符数组变成字符串

        //第二种:
        //1.把字符串变成字符数组
        char[] arr = str.toCharArray();
        //2.把字符数组中的元素进行位置交换
        //把最左边的字符移动到最右边,其实就是把字符数组中的第一个元素移动到最后一个位置
        //定义一个临时变量,临时存储第一个元素
        char temp = arr[0];
        //把剩余的元素往前挪一个位置
        for(int i = 1; i < arr.length; i++){
            arr[i-1] = arr[i];
        }
        //把临时变量存储的元素,赋值给最后一个位置
        arr[arr.length-1] = temp;
        //3.把字符数组变成字符串
        String result = new String(arr);
        return result;
    }

}


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

相关文章:

  • 【找工作】C++和算法复习(自用)
  • PHP+Apache+MySQL安装(Windows)
  • 从0开始的AI大模型学习---ollama+amd显卡本地化部署deepseek-r1
  • vue3 input type=“file” 修改样式
  • pdf转换成word在线 简单好用 支持批量转换 效率高 100%还原
  • Windows下Docker Compose使用教程
  • 游戏引擎学习第114天
  • java毕业设计之医院门诊挂号系统(源码+文档)
  • Redis-03高级篇中-多级缓存:
  • RK3588配置成为路由器
  • 网络初始2:网络编程--基于UDP和TCP实现回显器
  • Python中常见库 PyTorch和Pydantic 讲解
  • [Linux]——进程控制(中)
  • SpringSecurity基于配置方法控制访问权限:MVC匹配器、Ant匹配器
  • 【git】提交修改、回撤、回滚、Tag 操作讲解,与reset (--soft、--mixed、--hard) 的区别
  • ArkTS与ArkUI深度解析:鸿蒙应用开发的未来之路
  • Aseprite绘画流程案例(1)——画相机图标
  • Linux-C/C++《C++/1、C++基础》(C++语言特性、面向对象等)
  • 哈希表模拟封装unordered_map和unordered_set
  • 嵌入式 Linux 设备树中的标准属性详解