关于Java中的String类


String类

在这里插入图片描述

package com.atguigu.java;
import org.junit.Test;
/**
 * String的使用
 * ①String是声明为final的,不可以被继承
 * ②String实现了Serializable接口:表示字符串是支持序列化的
 *        实现了Comparable接口:表示String可以比较大小
 * ③String内部定义了final修饰的char型数组用于存储数据:数组不可以再被重新赋值,数组元素也不能再被修改
 * ④String代表不可变的字符序列。简称:不可变性
 *            体现:1,当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值
 *                 2,当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能在原有的value上进行赋值
 *                 3,当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值
 * ⑤通过字面量的方式(区别于new方式)给字符串赋值,此时的字符串值声明在字符串常量池中。
 * ⑥字符串常量池中是不会存储相同内容的字符串的
 *
 */
public class StringTest {
    @Test
    public void test1(){
        String s1="abc";   //字面量方式的定义方式
        String s2="abc";
        System.out.println(s1 == s2);  //true。表明s1、s2地址值一样,在内存中指向同一处
        s1="hello";
        System.out.println(s1);     //hello
        System.out.println(s2);     //abc
        System.out.println("***********");
        String s3="abc";
        s3+="def";
        System.out.println(s3);  //abcdef
        System.out.println("***********");
        String s4="abc";
        String s5 = s4.replace('a', 'm');
        System.out.println(s4); //abc
        System.out.println(s5); //mbc

    }
}

在这里插入图片描述

String对象的创建:

在这里插入图片描述在这里插入图片描述

package com.atguigu.java;
import org.junit.Test;
/**
 * String的实例化方式:
 * ①通过字面量方式
 * ②通过new加构造器的方式
 */
public class StringTest {
    @Test
    public void test1(){
        //通过定义字面量方式:此时的s1和s2的数据javaEE声明在方法区的字符串常量池中。
        String s1="javaEE";
        String s2="javaEE";
        //通过new加构造器方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
        String s3=new String("javaEE");
        String s4=new String("javaEE");

        System.out.println(s1 == s2); //true
        System.out.println(s1 == s3); //false
        System.out.println(s1 == s4); //false
        System.out.println(s3 == s4); //false
    }
}

在这里插入图片描述在这里插入图片描述
面试题:String s=new String(“abc”); 方式创建对象,在内存中共创建了几个对象?

两个。一个是堆空间中new结构,另一个是char[ ]型数组对应的常量池中的数据:“abc”。

package com.atguigu.java;
import org.junit.Test;
public class StringTest {
    @Test
    public void test1(){
        //通过定义字面量方式:此时的s1和s2、s3的数据javaEE声明在方法区的字符串常量池中。
        String s1="javaEE";
        String s2="hadoop";
        String s3="javaEEhadoop";
        String s4="javaEE"+"hadoop";  //s4也在字符串常量池

        String s5=s1+"hadoop";
        String s6="javaEE"+s2;
        String s7=s1+s2;

        System.out.println(s3==s4);   //true
        System.out.println(s3==s5);   //false
        System.out.println(s3==s6);   //false
        System.out.println(s3==s7);   //false
        System.out.println(s5==s6);   //false
        System.out.println(s5==s7);   //false
        System.out.println(s6==s7);   //false

        String s8=s5.intern();      //返回值得到的s8使用的是常量池中已经存在的”javaEEhadoop“
        System.out.println(s8 == s4);  //true
        System.out.println((s1+s2).intern()==s3);  //true

    }
}

在这里插入图片描述小知识点:

package com.atguigu.java;
import org.junit.Test;
public class StringTest {
    @Test
    public  void  test2(){
        String s1="javaEEHadoop";
        String s2="javaEE";
        String s3=s2+"Hadoop";
        System.out.println(s1 == s3);  //此处显然是false
        final String s4="javaEE";   //final修饰局部变量变为 *常量*
        String s5=s4+"Hadoop";
        System.out.println(s1 == s5); //true。因为常量与常量的拼接在常量池
    }
}


笔试练习:
在这里插入图片描述

package com.atguigu.exer;
/**
 *一道面试题
 */
public class StringTest {
    String str = new String("good");
    char[] ch = { 't', 'e', 's', 't' };
    public void change(String str, char ch[]) {  //根据值传递机制,引用数据类型传入的是地址。
        str = "test ok";
        ch[0] = 'b';
    }
    public static void main(String[] args) {
        StringTest ex = new StringTest();
        ex.change(ex.str, ex.ch);
        System.out.println(ex.str);   //good。String不可变性
        System.out.println(ex.ch);  //best。
    }
}


在这里插入图片描述

注意char型数组地址值赋给新变量(形参)ch[ ],则它们地址一样,都指向堆里的同一个数据,通过地址修改数组中第一个字母,数组没有不可变性,于是进行了修改变为best。

String常用方法一

package com.atguigu.java;
import org.junit.Test;
/**
 *  int length():返回字符串的长度: return value.length
 *  char charAt(int index): 返回某索引处的字符return value[index]
 *  boolean isEmpty():判断是否是空字符串:return value.length == 0
 *  String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
 *  String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
 *  String trim():返回字符串的副本,忽略前导空白和尾部空白
 *  boolean equals(Object obj):比较字符串的内容是否相同
 *  boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
 *  String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
 *  int compareTo(String anotherString):比较两个字符串的大小。返回负数:当前对象小;返回正数;当前对象大;返回0:相等
 *  String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
 *  String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
 */

public class StringMethodTest {
    @Test
    public  void test1(){
        String s1="HelloWorld";
        System.out.println(s1.length());  //10
        System.out.println(s1.charAt(0)); //H
        System.out.println(s1.charAt(9)); //d
        //System.out.println(s1.charAt(10)); //超出范围
        System.out.println(s1.isEmpty()); //false。实际看的是数组长度
        String s2 = s1.toLowerCase();
        System.out.println(s1);  // HellooWorld。s1是不可变的仍为原来字符串
        System.out.println(s2);  //helloworld。修改后的
        System.out.println(s2.toUpperCase()); //HELLOWORLD
        String s3="   he llo world   ";
        String s4 = s3.trim();
        System.out.println("-----"+s3+"-----"); //-----   he llo world   -----。s3没有变
        System.out.println("-----"+s4+"-----"); //-----he llo world-----。去除了首位尾的空格。可用于防止注册时在输入手机号首尾处用户误点空格

    }
    @Test
    public void test2() {
        String s1 = "HelloWorld";
        String s2 = "helloWorld";
        System.out.println(s1.equals(s2));   //false。String中重写了equals(),比较内容
        System.out.println(s1.equalsIgnoreCase(s2));  //true。比较时忽略大小写

        String s3="abc";
        String s4=s3.concat("def");
        System.out.println(s4);  //abcdef。concat拼接到尾部,不常用,多用+

        String s5="abc";
        String s6=new String("abe");
        System.out.println(s5.compareTo(s6));  //-2。涉及到字符串排序

        String s7="中国北京大学未名湖";
        String s8=s7.substring(6);  //索引为6处开始
        System.out.println(s8);  //未名湖

        String s9 = s7.substring(2, 6);  //注意此处结束时要写6!!!左闭右开的
        System.out.println(s9);  //北京大学

    }

}

String常用方法二

package com.atguigu.java;
import org.junit.Test;
/**
  boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
  boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
  boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
  boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
  int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引。
  int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
  int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
  int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
 注:indexOf和lastIndexOf方法如果未找到都是返回-1
 */

public class StringMethodTest {
    @Test
    public void  test3(){
        String str1="helloworld";
        boolean b1 = str1.endsWith("ld");
        System.out.println(b1);  //true

        boolean b2 = str1.startsWith("He");
        System.out.println(b2);  //false。区分大小写
        boolean b3 = str1.startsWith("he");
        System.out.println(b3);  //true
        System.out.println(str1.startsWith("ll", 2));  //true。指定索引处开始的
        String str2="wo";
        System.out.println(str1.contains(str2));  //true。看字符串str1中是否包含str2(区分大小写)
        System.out.println(str1.indexOf("lo"));  //3。
        System.out.println(str1.indexOf("lo",5)); //-1。从索引为5的位置往后找"lo",找不到

        String str3="hellorworld";
        System.out.println(str3.lastIndexOf("or")); //7。从后往前找相应字符串。
        System.out.println(str3.lastIndexOf("or",6)); //4
    }

}

String常用方法三

在这里插入图片描述在这里插入图片描述
回顾:String与基本数据类型、包装类之间的转化
在这里插入图片描述

package com.atguigu.java;
import org.junit.Test;
/*
*  String与基本数据类型、包装类之间的转换。
*  ①String--->基本数据类型、包装类:调用包装类的静态方法 parseXxx(str)
*  ②基本数据类型、包装类--->String:调用String重载的valueOf(xxx)
*/
public class StringTest {
    @Test
    public void test1(){
        String str1="123";   //在常量池里
        int num = Integer.parseInt(str1);

        String str2 = String.valueOf(num);  //"123",方式一
        String str3=num+"";  //方式二。有变量参与,在堆里
        System.out.println(str1==str2);  //false。一个在堆里,一个在常量池里
    }
}

String与char[ ](字符数组)之间的转换
在这里插入图片描述

package com.atguigu.java;
import org.junit.Test;
/*
*  String与char[]之间的转换。
*  ①String--->char[]:调用String的toCharArray
*  ②char[]--->String:调用String的构造器
*/
public class StringTest {
    @Test
    public void test1(){
        String str1="abc123";
        char[] charArray = str1.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            System.out.println(charArray[i]);
        }

        char[] arr=new char[]{'h','e','l','l','o'};
        String str2 = new String(arr);  //返回即为String型
        System.out.println(str2);  //hello

    }
}

String与byte[ ](字节数组)之间的转换

package com.atguigu.java;
import org.junit.Test;
import java.util.Arrays;
/*
*  String与byte[]之间的转换。
*  ①String--->byte[]:调用String的getBytes()
*  ②byte[]--->String:调用String的构造器
*/
public class StringTest {
    @Test
    public void test1(){
        String str1="abc123";
        byte[] bytes = str1.getBytes();
        System.out.println(Arrays.toString(bytes));  //[97, 98, 99, 49, 50, 51]为AsCll码。可以调用toString进行遍历

        System.out.println("**********");
        String str2 = new String(bytes);
        System.out.println(str2);  //字符串abc123
    }
}

练习:面试中String相关算法的考察

在这里插入图片描述

package com.atguigu.java;
import org.junit.Test;
/**
 *  模拟一个trim方法,去除字符串两端的空格。
 */
public class TrimTest {
    public String trim(String str){
        if (str!=null){
            int start=0;       //用于记录从前往后首次索引位置不是空格的位置的索引
            int end=str.length()-1;           //用于记录从后往前首次索引位置不是空格的位置的索引
            while(start<end&&str.charAt(start)==' '){
                start++;
            }
            while (end>start&&str.charAt(end)==' '){
                end--;
            }
            if (str.charAt(start)==' '){   //当end==start时,如果第一个位置为空格,则返回空字符串
                return "";
            }
            return str.substring(start,end+1);
        }
        return null;
    }
    @Test
    public void  testTrim(){
        String str="  Hekk  oo lLLrn   ";
        String str1=trim(str);
        System.out.println("____"+str1+"____");  //____Hekk  oo lLLrn____


    }
}

在这里插入图片描述方式一:字符串改成数组,对数组进行反转

package com.atguigu.java;
import org.junit.Test;
/**
 * 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”
 * 方式一:字符串改成数组,对数组进行反转
 */
public class ReverseTest {
    public String reverse(String str,int startIndex,int endIndex){
        if (str!=null&&str.length()!=0){
            char[] arr = str.toCharArray();
            for (int x = startIndex,y=endIndex; x <y ; x++,y--) {
                char temp=arr[x];
                arr[x]=arr[y];
                arr[y]=temp;
            }
            return new String(arr);
        }
        return null;
    }
    @Test
    public void testReverse(){
        String str="abcdefg";
        String reverse = reverse(str, 2, 5);
        System.out.println(reverse);//abfedcg
    }
}


方式二:使用String拼接。分成三部分

package com.atguigu.java;
import org.junit.Test;
/**
 * 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”
 * 方式二:使用String拼接。分成三部分
 */
public class ReverseTest {
    public String reverse(String str,int startIndex,int endIndex){
        if (str!=null&&str.length()!=0){
            String reverseStr=str.substring(0,startIndex);  //第一段子串。三段都是左闭右开
            for (int i = endIndex; i >=startIndex ; i--) {
                reverseStr+=str.charAt(i);     //第二段子串
            }
            reverseStr+=str.substring(endIndex+1,str.length());
            return reverseStr;
        }
        return  null;
    }
    @Test
    public void testReverse(){
        String str="abcdefg";
        String reverse = reverse(str, 2, 5);
        System.out.println(reverse);//abfedcg
    }
}


但方式二中如:reverseStr+=str.charAt(i); 是在现有的变量基础上拼接,每次都要新建一个对象。效率不高可以继续优化。

方式二优化:使用StringBuffer或StringBuilder

package com.atguigu.java;
import org.junit.Test;
/**
 * 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”
 * 方式二优化:使用StringBuffer或StringBuilder。有可变性,在底层原有的char型数组中操作效率更高
 */
public class ReverseTest {
    public String reverse(String str,int startIndex,int endIndex){
        if (str!=null&&str.length()!=0){
            StringBuilder builder=new StringBuilder(str.length());  //带参构造器
            //第一部分
            builder.append(str.substring(0,startIndex));
            //第二部分
            for (int i = endIndex; i >=startIndex ; i--) {
                builder.append(str.charAt(i));
            }
            //第三部分
            builder.append(str.substring(endIndex+1));
            return  builder.toString();  //转换成String型
        }
        return null;
    }
    @Test
    public void testReverse(){
        String str="abcdefg";
        String reverse = reverse(str, 2, 5);
        System.out.println(reverse);//abfedcg
    }
}


在这里插入图片描述方案1.0:

package com.atguigu.java;

import org.junit.Test;

/**
 * 获取一个字符串在另一个字符串中出现的次数。比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数
 *
 */
public class StringDemo {
    public int getCount(String mainStr,String subStr){ //获取subStr在mainStr中出现的次数
        int mainLength=mainStr.length();
        int subLength=subStr.length();
        int count=0;
        int index;
        if (mainLength>=subLength){
            while ((index=mainStr.indexOf(subStr))!=-1) {  //此处先把子串在主串中的索引赋值给index。若为-1表示没有找到
                count++;
                mainStr=mainStr.substring(index+subLength); //修改主串
            }
            return count;
        }else{
            return 0;
        }
    }
    @Test
    public void testGetCount(){
        String mainStr="abkkcadkabkebfkabkskab";
        String subStr="ab";
        int count = getCount(mainStr, subStr);
        System.out.println(count); //4
    }
}

但一些操作如:mainStr=mainStr.substring(index+subLength); 需要每次造一个mainStr。可以进行优化。

方案2.0改进:

在这里插入图片描述

package com.atguigu.java;

import org.junit.Test;

/**
 * 获取一个字符串在另一个字符串中出现的次数。比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数
 *
 */
public class StringDemo {
    public int getCount(String mainStr,String subStr){ //获取subStr在mainStr中出现的次数
        int mainLength=mainStr.length();
        int subLength=subStr.length();
        int count=0;
        int index=0;
        if (mainLength>=subLength){
            while ((index=mainStr.indexOf(subStr,index))!=-1) {  //此处要注意体会
                count++;
                index+=subLength;
            }
            return count;
        }else{
            return 0;
        }
    }
    @Test
    public void testGetCount(){
        String mainStr="abkkcadkabkebfkabkskab";
        String subStr="ab";
        int count = getCount(mainStr, subStr);
        System.out.println(count); //4
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过期动态

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值