【JAVA基础】字符串


字符串

  • 创建方式 String 变量名 = “字符串内容”;

在这里插入图片描述

  • 例1
String a = "123"; // 创建字符串
String c = "123";
System.out.println(a == c);

结果为:true 这是因为java堆内存中字符串常量池中将相字符串的地址共享,节约内存空间

在这里插入图片描述

  • 例2
String a = "123"; // 创建字符串
String c = "123";
System.out.println(a == c);

String b = new String("123"); // new 关键字是在堆内存中开辟内存空间的意思
System.out.println(a == b); // == 对于基本数据类型来说==进行的是值的判断,对于引用数据类型来说==比较的是当前地址是否相同

int a1 = 10;
int b1 = 10;
System.out.println(a1 == b1);

在判断a==b时,结果为false,而在判断a1==b1时,结果为true,因为对于基本数据类型来说==进行的是值的判断,对于引用数据类型来说==比较的是当前地址是否相同

在这里插入图片描述

  • 例3

equals方法

 // 方法内部
	public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

// equals()方法首先比较的是地址是否相等,如果相等返回true,如果不相等比较的是值是否相等
// 基本数据类型只能用 == 判断,无法调用equals

当基本数据类型尝试调用equals()方法:

在这里插入图片描述

会产生报错,因为基本数据类型无法调用equals

常用字符串方法

  • 创建字符串
String a = "Hello World!"; //创建字符串
  • length( )方法,获取字符串长度
// length()方法 获取字符串长度
int length= a.length();
System.out.println(length);

输出结果:在这里插入图片描述

  • 获取指定字符
// charAt(index) 根据位下标获取指定的字符(下标从0开始)
char ch = a.charAt(4);
System.out.println(ch);

输出结果:在这里插入图片描述

  • 截取字符串
// subString(index)方法 从第index下标截取字符串(包含index),或者是个左闭右开的区间[m,n)
String b = a.substring(6);
System.out.println(b);
String c = a.substring(6,10); // [6,10)
System.out.println(c);

输出结果:在这里插入图片描述

  • 判断是否有子串
// contains()方法 判断是否有子串
System.out.println(a.contains("llo"));

输出结果:在这里插入图片描述

  • 字符串替换
//字符串替换 replace(char oldChar,char newChar)
String newa = a.replace('o','x');
System.out.println(newa);
String newb = a.replace("World","admin");
System.out.println(newb);

输出结果:在这里插入图片描述

  • 字符串分割
// 字符串分割 split()
String str = "apple,banana,orange";
String[] parts = str.split(","); // 以","分割str字符串
System.out.println(Arrays.toString(parts));
for (int i = 0;i<parts.length;i++){
    System.out.println(parts[i]);

输出结果:在这里插入图片描述

KMP算法

在大串中找到小串

  • 例子:现在要在aabaabaafa字符串中找到aabaaf

    传统解法:利用双层for循环

    1. 两个游标从前向后进行遍历,并且比较值是否相等,如果相等执行i++,j++

    2. 如果不相等,则i游标回到下标为1的位置,j游标归0从新开始

      这种算法时间复杂度较高O(n2)

    在这里插入图片描述

    KMP算法

    1. 两个游标从前向后进行遍历,并且比较值是否相等,如果相等则i++,j++;如果不相等,那么转到步骤二

    2. 让游标i不动,游标j指向b

      但是如何将下标指向b?

      答:需要找到最长相等的前后缀长度,要用到前缀表(常用的是next表)

      对于字符串:aabaaf

      前缀:不包含最后一个字符的所有以第一个字符开头的连续子串

      ​ a、aa、aab、aaba、aabaa

      后缀:不包含第一个字符的所有以最后一个字符结尾的连续子串

      ​ f、af、aaf、baaf、abaaf

      此时找到最长相等的前后缀长度过程如下:

      a 只有a,没有前后缀

      aa 前缀为a,后缀为a,最长相等的前后缀长度为1

      aab 前缀:a、aa,后缀:b、ab,最长相等的前后缀长度为0

      aaba 前缀:a、aa,aab后缀:a、ba,aba最长相等的前后缀长度为1

      aabaa 前缀:a、aa,aab、aaba后缀:a、aa,baa、abaa,最长相等的前后缀长度为2

      aabaaf 前缀:a、aa,aab、aaba、aabaa后缀:f、af、aaf、baaf、abaaf,最长相等的前后缀长度为0

      所以构建出来的前缀表为:

      前缀表010120
      数组aabaaf

      然后就可以根据前缀表,找到b所在的位置,将游标j定位

      • 前缀表和next数组

        很多KMP算法的实现都是使用next数组来做回退操作,那么next数组与前缀表有什么关系呢? next数组就可以是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)之后作为next数组。如下图

        在这里插入图片描述

字符串拼接

反编译javap -c

例1

String s1 = "123";
String s2 = "456";
String s3 = s1+s2;  // 编译期间调用了stringBuffer里面的append()方法 其中为s3开辟了新的内存地址
System.out.println(s3);
String s4 = "123456";
System.out.println(s3 == s4);  // 结果为false

正常的话s3的值为字符串123456,而s4的值也是字符串“123456”,java中相同字符串本应该共享字符串常量池,s3与s4指向的地址应该一样,但是最终判断结果并不为true,是因为String s3 = s1+s2; 编译期间调用了stringBuffer里面的append()方法 其中为s3开辟了新的内存地址,导致s3与s4指向的地址并不一样。

在这里插入图片描述

例2

String s1 = "123" + "456"; // 编译期间直接进行自动拼接
String s2 = "123456";
System.out.println(s1 == s2);  // 结果为true

而上面这段代码中,s1 = “123” + “456”,在编译过程中并没有调用方法开辟新的内存空间,而是直接将"123"、"456"两个字符串拼接并赋值给了s1,所以在最终判断时结果为true

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值