Java中StringBulider运行效率为什么比String更快?String、StringBulider知识点详解(黑马Java基础笔记)

视频链接

黑马程序员Java视频教程,一套超哇塞的Java教程,java零基础自学入门必看黑马java教程_哔哩哔哩_bilibili


目录

视频链接

Scanner录入字符串

String类

特点

构造方法

构造方法区别

常见面试题

StringTable

两种构造方式的内存

String变量与常量拼接

String常量拼接

比较方法

案例-用户登录

遍历方法

案例——统计字符次数

截取方法

案例1——手机号屏蔽

替换方法

案例1——敏感词替换

 切割方法

方法小结

StringBuilder

构造方法

四个方法

案例1——检查对称字符串

 案例2——输出数组元素

为什么StringBuilder的效率高

StringBuffer


Scanner录入字符串

String next()        遇见空格或者tap就不继续录入了

String nextLine()        以回车作为录入的结束标记

两者各有弊端

next会录入不完整;nextLine不能在nextInt、nextDouble等方法后面使用

对于目前的学习来说,如果我们的用户输入全是字符串,我们用nextLine();如果输入还有除字符串之外的其他类型,我们用next()


String类

特点

  • Java中所有的双引号字符串,都是String这个类的对象
  • 字符串内容不可改变,想要更改只能用新的对象做替换
  • String字符串可以被共享(StringTable)

字符串常量池:但我们使用双引号创建String对象的时候,会检查常量池中是否有该数据

不存在:创建对象,常量池中创建内存并保存地址

存在:复用

在JDK7版本之前StringTable字符串常量池 在方法区里

JDK7及以后版本StringTable在堆空间里


构造方法

  • public String():创建一个空白字符串,里面不含任何内容
  • public String(char[] chs):根据传入的字符数组,创建字符串对象
  • public String(string original):根据传入的字符串,来创建字符串对象

这三个构造方法都没有直接双引号“abc”用的方便,但其实有区别


构造方法区别

String是Java中唯一可以用双引号直接创建对象的类,特殊!

除了双引号创建,上面三个是常见的构造方法


常见面试题

StringTable

回答:结果是true,因为创建s1对象的时候,在字符串常量池StringTable中也创建了空间保存地址,在创建s2的时候先检查StringTable,里面有“abc”字符串,所以直接复用同一地址。


两种构造方式的内存

回答:s1对象是双引号创建的,创建时在堆内存中的StringTable保存内存地址,(注意:String的value保存方式是字符数组Type[]);

创建s2的时候,先new,在堆内存中开辟自己的一个内存空间,然后创建双引号“abc”对象,在StringTable中查找字符串,发现“abc”就复用地址,将该字符串的副本作为新创建的String对象,(以字符数组的形式)保存在开辟的内存空间中,所以创建s2的时候其实创建了两次String对象

最终的结果肯定是False,s1的内存空间保存在StringTable中,而s2是在堆内存中自己开辟的空间,只不过创建的字符串是StringTable中s1的副本!


String变量与常量拼接

回答: 

创建s1和s2以及“c”三个对象,都会在串池中记录地址,然后s3需要对字符串变量和常量“c”进行字符串拼接,会调用StringBuilder类中的append方法,将s2和“c” 拼接成“abc”,但此时“abc”是StringBuilder类型不能直接给s3,所以会调用StringBuilder中的toString方法,在堆内存中创建空间保存String对象“abc”,所以s1和s3的内存地址不一样,输出是False!

s1内存地址在串池当中保存,s3的内存地址是StringBulider调用toString方法之后开辟的新空间中保存


String常量拼接

 回答:由于Java具有常量优化机制,在编译成字节码文件的时候,会先对变量运算进行处理,所以这段代码编译出来的字节码文件中s2已经是"abc"了,内存中的保存和第一题一样,s1会保存在串池当中,s2直接复用,所以结果为True


比较方法

  • public boolean equals方法(要比较的字符串)
  • public boolean equalslgnorecase(要比较的字符串)
    完全一样结果才是true,否则为false
    忽略大小写的比较(验证码比较字符串常用!)

案例-用户登录

需求分析:明确循环次数三次,使用for循环,判断条件:用户名和密码equals(输入的用户名和密码)都正确,则提示登录成功,前两次失败显示登录失败,三次失败后显示次数已经用完。

package com.yuhan.domain;
import java.util.Scanner;
public class StringDemo2 {
    public static void main(String[] args) {
        String admin = "zhaosi";
        String password = "1974abcd";

        checkPassword(admin,password);
    }
    public static void checkPassword(String admin,String password) {
        Scanner sc=new Scanner(System.in);
        for (int i = 2; i >=0; i--) {
            System.out.println("请输入账号:");
            String inputA=sc.nextLine();
            System.out.println("请输入密码:");
            String inputB=sc.nextLine();
            if (admin.equals(inputA) && password.equals(inputB)) {
                System.out.println("恭喜您,登录成功!");
                return;
            }
            else
            {
                if(i==0)
                {
                    System.out.println("对不起您的登录机会已经用完");
                    return;
                }
                else
                {
                    System.out.println("对不起,您的账号或密码输入有误,请重新输入,您还有"+i+"次机会");
                    System.out.println("------------------------------------------------------------");
                }
            }

        }

    }
}

注意最后一次如果输错的话提前结束循环,不要打印出来剩余0次机会


遍历方法

public char[]toCharArray()将此字符串转换为一个新的字符数组

返回指定索引处的char 值public char charAt(int index)

如果主方法和建立的方法是平级的,那么我们要加static

String对象.length()————返回int整数值,字符串的长度

案例——统计字符次数

案例分析:三个count值,用toCharArray()生成的字符数组进行遍历,每个字符进行判断,最终输出 

package com.yuhan.domain;

import java.util.Scanner;

public class StringDemo3 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您想统计的字符串:");
        String s1 = sc.nextLine();

        staticString(s1);
    }

    public static void staticString(String s) {
        int xiaoxieCount = 0, daxieCount = 0, numCount = 0;
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] >= 'a' && chars[i] <= 'z') {
                xiaoxieCount++;
            } else if (chars[i] >= 'A' && chars[i] <= 'Z') {
                daxieCount++;
            } else if (chars[i] >= '0' && chars[i] <= '9') {
                numCount++;
            }
        }
        System.out.println("该字符串中有小写字母:" + xiaoxieCount + "个");
        System.out.println("该字符串中有大写字母:" + daxieCount + "个");
        System.out.println("该字符串中有数字字母:" + numCount + "个");


    }
}

运行结果


截取方法

String类的截取方法

public String substring(int beginIndex): 根据传入的索引开始做截取,截取到字符串的末尾public String substring(int beginIndex,int endIndex): 根据传入的开始和结束索引,对字符串做截取        -包含头,不包含尾

 注意截取出来的新字符串要用新的String对象接受,两个截取方案都是有返回值的

案例1——手机号屏蔽

 需求分析:将Scanner输入的手机号分为三段并做拼接最终输出,用substring

package com.yuhan.domain;

import java.util.Scanner;

public class StringDemo4 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入十一位手机号码:");
        String phoneNum = sc.nextLine();

        String s1 = phoneNum.substring(0, 3);
        String s2 = phoneNum.substring(7);
        System.out.println("屏蔽后的手机号码为:" + s1 + "****" + s2);
    }
}

替换方法

String类的替换方法:
public String replace(CharSequence target, CharSequence replacement)
参数1 :旧值
参数2 : 新值 

案例1——敏感词替换

package com.yuhan.domain;

import java.util.Scanner;
public class StringDemo5 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您想对策划说的话:");
        String str = sc.nextLine();
        String result =str.replace("TMD","***");
        System.out.println(result);

    }
}

 切割方法

String类的切割方法:
public String[] split(String regex): 根据传入的字符串作为规则,切割当前字符串

 在切割的时候.代表任意字符,不能直接作为制定规则,使用的时候要用\\.

使用split的时候先正常使用规则,如果不对就加两个斜线


方法小结

public boolean equals方法(要比较的字符串)比较内容:
public boolean equalsIgnorecase(要比较的字符串):比较内容,忽略大小写
public char[] toCharArray()将字符串转换为字符数组
public char chatAt(int index)根据索引找字符
public int length():返回字符串的长度
public string substring(int beginIndex)截取到末尾

public string substring(int beginIndex, int endIndex)根据开始和结束索引做截取,包含头不包含尾
public string replace(旧值,新值)替换
public string[] split(string regex):切割


StringBuilder

可以提高字符串的操作效率 

介绍:

1.一个可变的字符序列
2.StringBuilder是字符串缓冲区,将其理解是容器,这个容器可以存储任意数据类型,但是只要进入到这个容器,全部变成字符串。


构造方法

public StringBuilder()                        创建一个空的字符串缓冲区(容器)
public StringBuilder(String str)        创建一个字符串缓冲区,并初始化好指定的参数内容


四个方法

1.public StringBuilder append(任意类型):添加数据,并返回对象自己
2.public stringBuilder reverse():将缓冲区中的内容,进行反转
3.public int length():返回长度
4.public String toString():将缓冲区的内容,以String字符串类型返回

public class StringBuilderDemo2 {
    public static void main(String[] args) {

        StringBuilder sb= new StringBuilder();
        sb.append("Hello").append("World").append("!");
        System.out.println(sb);
    }
}

 这里面采用了链式编程思想,append返回的是对象,就可以继续向下调用方法,String中的subString也是一样。

反转同上,因为返回的是对象,所以可以重复调用

toString适用于的情况:数据在StringBuilder中,但是我要调用String的方法,所以要用toString转换为String类型再处理数据


案例1——检查对称字符串

分析:对称字符串的反转一模一样,输入的String先变成StringBuilder用翻转方法,再用toString方法变成字符串对象,才能用equals和输入的字符串进行比较

package com.yuhan.StringBuilder;

import java.util.Scanner;

public class StringBuilderDemo2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入要判断的字符串:");
        String str = sc.nextLine();

        StringBuilder sb1 = new StringBuilder(str);
        String result = sb1.reverse().toString();
        System.out.println("该字符串是否为对称字符串:" + str.equals(result));
    }
}

 


案例2——输出数组元素

分析:建立StringBuilder,循环遍历数组进行append,注意字符串格式,最终toString接收并输出

package com.yuhan.StringBuilder;

public class StringBuilderDemo3 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        String result = changeStr(arr);
        System.out.println(result);
    }

    public static String changeStr(int[] arr) {
        StringBuilder sb = new StringBuilder("[");
        sb.append(arr[0]);
        for (int i = 1; i < arr.length; i++) {
            sb.append(", ").append(arr[i]);
        }
        sb.append("]");
        return sb.toString();
    }
}

 [1, 2, 3, 4, 5]

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


为什么StringBuilder的效率高

字符串拼接的时候,需要在堆内存中先创建一个StringBuilder对象再toString创建String对象 

所以频繁运用字符串拼接的时候,优先用StringBuilder 


StringBuffer

构造方法和使用方法和Builder一样,只不过StringBuffer针对多线程任务是安全的,效率偏低;StringBuilder针对多线程任务是相对不安全的,效率高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值