【Java学习】认识String类【详解篇16】

本文详细讲解了Java中的String类,包括定义字符串的不同方式、字符串常量池、比较和操作技巧(如首字母大写、字符串反转、连接与拆分)。深入理解字符串的不可变性,以及如何使用StringBuilder和 StringBuffer进行高效操作。
摘要由CSDN通过智能技术生成

【前言】代码的注释较多,因为还有很多细节的知识点大都写在代码的注释中,我觉得将知识点和代码结合起来可能会更容易理解,所以很多时候还是结合代码来看会更好。

认识String类

C语言当中是没有字符串类型的,但是在Java当中是有字符串类型的。

如何定义一个字符串?

public static void main(String[] args) {
        String str1="hello";//写法一
        System.out.println(str1);
        String str2=new String("abcdef");//写法二:调用了带有一个参数的String构造方法,来构造String
        //对象,并赋值给str2
        System.out.println(str2);
        char[] val={'h','i','g','k','l','m'};//写法三
        String str3=new String(val);
        System.out.println(str3);
        //offset:起始位置的偏移量
        //定义字符串平常用的最多的就是这三种方式,这三种方式中用的最多的是第一种
        //△提醒:在真正的笔试面试过程当中,字符串、数组和单链表的题型是非常多的,建议多多练习刷题。
    }

字符串的比较

public static void main(String[] args) {
        //比较str1、str2、str3,判断是否相等?
        /*str1和str2是引用类型,引用类型放的是地址,所以等号两边比较的值是地址*/
        String str1="hello";
        String str2=new String("hello");
        System.out.println(str1==str2);//F

        String str3="hello";
        System.out.println(str1==str3);//T
    }

上述代码为false和true的原因:代码所对应的内存底层的位置如图所示

image-20210925220311231

image-20210925215328818

public static void main(String[] args) {
        String str1="hello";
        String str2="hel"+"lo";
        //双引号引起来的叫做字符串常量,常量有一个特点是:在编译时已经处理完了,也就是说常量在编译时就已经变成“hello"了
        System.out.println(str1==str2);//T
        String str3=new String("hel")+"lo";
        System.out.println(str3==str1);//F
    }

上述代码为false和true的原因:代码所对应的内存底层的位置如图所示

image-20210925222850099

字符串常量池

字符串常量池的特点:

1、在JDK1.7开始,这个常量池被挪到堆里面了

2、在常量池里面所存放的数据是不重复的

3、字符串常量池并不是用来放常量的,它只放字符串常量

代码示例:

public static void main4(String[] args) {
        //《字符串常量池》
        //修改str1,str2会改变吗?
        String str1="hello";
        String str2=str1;
        System.out.println(str1);
        System.out.println(str2);

        str1="AAA";
        System.out.println(str1);
        System.out.println(str2);
//引用的指向发生了改变,如果通过str1去修改其指向的内容,str2会发生改变,但是在java字符串是常量,常量是不能被修改的。
    }
 public static void func(String str,char[] array) {//定义一个方法,并传参
        str="aaaaaa";
        array[0]='g';
    }
    public static void main5(String[] args) {
        String str1="hello";
        char[] val={'a'};
        System.out.println(str1);
        System.out.println(Arrays.toString(val));
        func(str1,val);//调用func,并将str1和val的值传过去
        System.out.println(str1);//结果没变
        System.out.println(Arrays.toString(val));//结果变了
    }

image-20210926182917687

字符串比较相等

 public static void main6(String[] args) {
        String str1="hello";
        String str2=new String("hello");
        System.out.println(str1==str2);//这里比较的是引用
        System.out.println(str1.equals(str2));//这里比较的是字符串的内容
        //如果想要比较字符串的内容是否相同可以使用equals
        //一般情况下,如果调用equals,没有重写的话默认是调用Object的equals方法,他的实现是默认比较引用是否相同。
        String str3="hello";
        System.out.println(str1==str3);//
        System.out.println(str1.equals(str3));
    }
/*使用equals需要有一些注意事项:
     * equals点号前面不能是null,否则会报错出现空指针异常,但是equals后面的括号是可以为null的,所以一般情况下,
     * 使用写法1方式写比较好,避免出现空指针异常*/
    public static void main7(String[] args) {
        String str1=null;
        String str2=new String("hello");
        System.out.println(str2.equals(str1));//写法1
        System.out.println(str1.equals(str2));//写法2
    }
//写法1
public static void main8(String[] args) {
        String str1="hello";
        String str2=new String("hello");
        System.out.println(str1==str2);//打印结果:false
    }
//写法2
public static void main8(String[] args) {
        String str1="hello";
        String str2=new String("hello").intern();
        System.out.println(str1==str2);//打印结果:true
    }

为false的原因如图:

image-20210926183442563

为true的原因如图:

image-20210926183515356

理解字符串不可变

public static void main9(String[] args) {
        String str="hello";//str是常量,"hello"是变量,这里表示变量str所指向的是一个常量
        str=str+"world";//在编译的时候str和”world“是不会进行拼接的,因为str是常量,”world“是变量
        str+="!!!";
        System.out.println(str);//打印结果:helloworld!!!
        for(int i=0;i<1000;i++){
            str+=1;
        }
/*这种拼接字符串的方式不可取,因为虽然只要最后一次的结果,但是实质在堆中已经产生了大量的临时变量
所以不能这样拼接字符串,那该怎么拼接呢?后面会学习:StringBuffer、StringBuilder,通过这两个可以解决这个问题,但这里暂且先不说。
 注意:字符串在java中是一个常量,每次拼接都会产生一个新的对象
 字符串不可变就是只要拼接或者指向其他的,只会生成一个全新的而不会在原来的基础上进行修改。*/
    }
 public static void main11(String[] args) throws NoSuchFieldException, IllegalAccessException {
        String str="Hello";
        //如何以修改的方式将大写的H改成小写的h呢?
        //需要利用反射,反射就是java程序自省的过程,也可以认为是java程序的一个bug
        //反射一般用在框架当中,反射的特点是在类外不仅可以获得私有方法,所有的东西在类外都可以使用反射的达到。
        /*要反射一个类,第一步是要拿到这个类的class对象,通过.class就可以拿到*/
        Class cl=String.class;
        Field field = cl.getDeclaredField("value");//括号里的value并不是随便写的,而是指拿到String里面的value字段
        field.setAccessible(true);//设置为true相当于说原来是私有的,设置为true就可以修改它了(相当于把它的权限打开了),不设置为true的话,反射修改也修改不了。
        char[] value=(char[]) field.get(str);//把结果强转成一个char类型的数组,此时value里面就拿到了需要的value数据
        value[0]='h';//这时就可以通过修改0号下标进行修改了
        System.out.println(str);//打印结果:hello,这时就被修改了
//所以,通过反射可以去修改私有的东西
        /*对于反射只需要明白:什么是反射?反射可以做什么?就好了*/
        
    }
    public static void main10(String[] args) {
        String str = "Hello";
        str = "h" + str.substring(1);//substring(1)表示从字符串的1号位置进行提取,提取完之后就变成了ello,然后小写h
        //拼上赋值给str,再打印,但是在这个过程中并不是把原来的Hello修改成hello,而是又产生了一个新的hello对象
        System.out.println(str);
    }

总结:

1、当遇到字符串,要明白它的内存结构;

2、字符串的不可变是什么意思;

3、在函数的内修改它的指向并不会影响实参的指向。

字符、字节与字符串

字符与字符串

字符串内部包含一个字符数组,String 可以和 char[] 相互转换.

下面是字符和字符串之间的相互转换用到的方法和代码示例

1️⃣将字符数组中的所有内容变为字符串:使用构造方法,public String(char value[])

 public static void main1(String[] args) {
        /*String 有一个参数char value[]:将字符数组中的所有内容变为字符串*/
        char[] value={'q','w','e','r','t','y'};
        String str=new String(value);
        System.out.println(str);
    }
//打印结果:qwerty

2️⃣将部分字符数组中的内容变为字符串:使用构造方法public String(char value[],int offset,int count)

public static void main(String[] args) {
        /*String 有两个参数char value[],int offset,int count将部分字符数组中的内容变为字符串*/
        char[] value={'q','w','e','r','t','y'};
        String str=new String(value,1,3);//偏移量
        System.out.println(str);
    }
//打印结果:wer

3️⃣取得指定索引位置的字符,索引从0开始:使用普通方法 public char charAt(int index)

public static void main(String[] args) {
        //取得指定索引位置的字符,索引从0开始
        String str2="hello";
        char ch=str2.charAt(0);
        System.out.println(ch); 
    }
//打印结果:h

4️⃣将字符串变为字符串数组返回:使用普通方法 public char[] toCharArray()

  public static void main(String[] args) {
        //将字符串变为字符串数组返回
       String str2="hello";
       char[] value2= str2.toCharArray();
       System.out.println(Arrays.toString(value2));
    }
//打印结果:[h, e, l, l, o]

代码示例: 给定字符串一个字符串, 判断其是否全部由数字所组成.

思路: 将字符串变为字符数组而后判断每一位字符是否是" 0 “~”‘9’"之间的内容,如果是则为数字.

//给一个字符串, 判断其是否全部由数字所组成.
    public static boolean isNumber(String str) {//定义一个函数,将str传过去
        for(int i=0;i<str.length();i++){
            char ch=str.charAt(i);//通过charAt访问字符串下标
            if(ch<'0'||ch>'9'){
                return false;
            }
        }
        return true;
    }
    public static void main(String[] args) {
        String str="1234567";
        boolean flg=isNumber(str);//flg接收,类型为 boolean
        System.out.println(flg);
    }
//打印结果:true
字节与字符串

字节常用于数据传输以及编码转换的处理之中,String 也能方便的和 byte[] 相互转换

字节与字符串的相互转换

1️⃣将字节数组变为字符串:使用构造函数,public String (byte bytes[])

public static void main(String[] args) {
        //通过字节数组构造字符串
        byte[] bytes={97,98,99,100};
        String str=new String(bytes);
        System.out.println(str);
    }
//打印结果:abcd

2️⃣将部分字节数组中的内容变为字符串:使用构造函数,public String (byte bytes[],int offset,int length)

3️⃣将字符串以字节数组的形式返回:使用普通函数,public byte[] getBytes()

public static void main(String[] args) {
        String str1="abcdef";
        byte[] bytes1=str1.getBytes();
        System.out.println(Arrays.toString(bytes1));
    }
//打印结果:[97, 98, 99, 100, 101, 102]

4️⃣编码转换处理:使用普通方法,public byte[] getBytes(String charsetName) throws UnsupportedEncodingException

 public static void main(String[] args) throws UnsupportedEncodingException {
        String str2="呵呵";
        byte[] bytes2=str2.getBytes("utf-8");
     System.out.println(Arrays.toString(bytes2));
    }
//打印结果:[-27, -111, -75, -27, -111, -75]

小结:

那么何时使用 byte[], 何时使用 char[] 呢?

  • byte[] 是把 String 按照一个字节一个字节的方式处理(如视频、音频), 这种适合在网络传输, 数据存储这样的场景下使用(). 更适合

针对二进制数据来操作.

  • char[] 是吧 String 按照一个字符一个字符的方式处理, 更适合针对文本数据来操作, 尤其是包含中文的时候。

回忆概念: 文本数据 vs 二进制数据

一个简单粗暴的区分方式就是用记事本打开能不能看懂里面的内容.

如果看的懂, 就是文本数据(例如 .java 文件), 如果看不懂, 就是二进制数据(例如 .class 文件

字符串常见操作

字符串比较

上面使用过String类提供的equals()方法,该方法本身是可以进行区分大小写的相等判断。除了这个方法之外,String类还提供有如下的比较操作:

NO方法名称类型描述
1public boolean equals(Object anObject)普通区分大小写比较
2public boolean equalsIanoreCase(String anotherString)普通不区分大小写比较
3public int compareTo(String anotherString)普通比较两个字符串的大小关系

代码示例:

public static void main(String[] args) {
        String str1="ABCDEF";
        String str2="abcdef";
    //(1)区分大小写比较
        System.out.println(str1.equals(str2));
    //(2)忽略大小写进行比较
        System.out.println(str1.equalsIgnoreCase(str2));
    //(3)compareTo方法比较两个字符串的大小关系
    
        String str3="abc";
        System.out.println(str3.compareTo(str2));
        //str3>str2    返回的是一个正数
        //str3<str2    返回的是一个负数
        //str3=str2    返回的是一个0
        System.out.println("巴".compareTo("王"));//java当中用的是unicode表,"巴"和"王"都是一个字符
        // 它们在unicode表中对应一个数字
    }
//打印结果:
false
true
-3
-5527

在String类中compareTo()方法是一个非常重要的方法,该方法返回一个整型,该数据会根据大小关系返回三类内容:

  1. 相等:返回0.
  2. 小于:返回内容小于0.
  3. 大于:返回内容大于0

compareTo()比较的代码示例:

System.out.println("A".compareTo("a")); // -32 
System.out.println("a".compareTo("A")); // 32 
System.out.println("A".compareTo("A")); // 0 
System.out.println("AB".compareTo("AC")); // -1 
System.out.println("刘".compareTo("杨"));

compareTo()是一个可以区分大小关系的方法,是String方法里是一个非常重要的方法。

字符串的比较大小规则, 总结成三个字 “字典序” 相当于判定两个字符串在一本词典的前面还是后面. 先比较第1个字符的大小(根据 unicode 的值来判定), 如果不分胜负, 就依次比较后面的内容.

字符串查找

从一个完整的字符串之中可以判断指定内容是否存在,对于查找方法有如下定义:

NO方法名称类型描述
1public boolean contains(CharSequence s)普通判断一个子字符串是否存在
2public int indexOf(String str)普通从头开始查找指定字符串的位置,查到了返回位置的开始索引,如果查不到返回-1
3public int indexOf(String str,int formIndex)普通从指定位置开始查找子字符串的位置
4public int lastIndexOf(String str)普通由后向前查找子字符串的位置
5public int lastIndexOf(String str,int fromIndex)普通从指定位置由后向前查找
6public boolean startsWith(String prefix)普通判断是否以指定字符串开头
7public boolean startsWith(String prefix,int toffset)普通从指定位置开始判断是否以指定字符串开头
8public boolean endWith(String suffix)普通判断是否以指定字符串结尾

1️⃣contains()方法:判断一个子字符串是否存在

public static void main(String[] args) {
        //《字符串查找》
        //contains()方法:判断一个子字符串是否存在
        String str="aaabbbcccddd";
        boolean flg= str.contains("abc");//contain的返回值是boolean类型,判断是否包含字符串
        System.out.println(flg);
        boolean flg1= str.contains("aaa");
        System.out.println(flg1);
    }
//打印结果:true

boolean flg= str.contains(“abc”)这里,为什么可以传字符串呢?

因为contains的返回值是boolean类型,参数是CharSequence

image-20210927082523956

而String的源码实现了CharSequence 接口,所以可以这样写!

image-20210927082236367

2️⃣indexOf()方法

//indexOf()方法:传一个参数,从头开始查找指定字符串的位置,查到了返回位置的开始索引,如果查不到返回-1
        String str1="aaabcabcabcd";
        int ret1=str1.indexOf("abc");//indexOf的返回值是int类型
        System.out.println(ret1);
//indexOf()方法:传两个参数,从指定位置开始查找子字符串的位置
        String str2="aaabcabcabcd";
        int ret2=str2.indexOf("abc",6);
        System.out.println(ret2);
//打印结果:
2
8

3️⃣lastIndexOf()方法

// lastIndexOf()方法:传一个参数,由后向前查找子字符串的位置
        String str3="abbcabcabcd";
        int index=str3.lastIndexOf("abc");
        System.out.println(index);
// lastIndexOf()方法:传两个参数,从指定位置由后向前查找
        int index1=str3.lastIndexOf("bc",3);//指定从某个位置开始找,但是要匹配的话
        //是可以跳过的
        System.out.println(index1);
//打印结果:
7
2

4️⃣startsWith()方法

//startsWith()方法:一个参数,判断是否以指定字符串开头
        String str4="abbcabcabcd";
        boolean ret3=str4.startsWith("ab");
        System.out.println(ret3);
        boolean ret4=str4.startsWith("abc");
        System.out.println(ret4);
//startsWith()方法:两个参数,从指定位置开始判断是否以指定字符串开头
        boolean ret5=str4.startsWith("abc",1);
        System.out.println(ret5);
        boolean ret6=str4.startsWith("abc",4);
        System.out.println(ret6);
//打印结果:
true
false
false
true

5️⃣endsWith()方法:判断是否以指定字符串结尾,它只能有一个参数。

        String str5="abbcabcabcd";
        boolean ret7=str4.endsWith("ab");
        System.out.println(ret7);
        boolean ret8=str4.endsWith("cd");
        System.out.println(ret8);
//打印结果:
false
true

面试问题:在主串当中查找子串。把这个东西叫做字符串匹配/查找算法。

他有两种算法:朴素算法和KMP算法

如果让你自己实现一个indexof方法,你该如何实现?

这个问题考的就是这两种算法,自己研究这两种算法并写出代码。

字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:

NO方法名称类型描述
1public String replaceAll(String regex,String replacement)普通替换所有的指定内容
2public String replaceFirst(String regex,String replacement)普通替换首个内容

image-20210927073953918

 public static void main(String[] args) {
        //《字符串替换》
        //(1)替换字符
        String str1="ababcabcd";
        String ret=str1.replace('a','A');//把原来的'a'字符换成'A'字符,返回值是String
        //返回的是一个新的对象
        System.out.println(ret);
        //(2)替换所有的指定内容
        String ret1=str1.replaceAll("ab","AB");
        System.out.println(ret1);
        //(3)替换首个内容,即替换第一次出现的字符串
        String ret2=str1.replaceFirst("ab","WW");
        System.out.println(ret2);
    }

注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.

字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

可用方法如下:

NO方法名称类型描述
1public String[] split(String regex)普通将字符串全部拆分
2public String[] split(String regex,int limit)普通将字符串部分拆分,该数组长度就是limit极限

split这个方法的返回值是一个数组,所以需要拿数组来接收。

image-20210927092719635

public static void main(String[] args) {
//split()方法:一个参数时,将字符串全部拆分
        String str="abc de f";
        //split这个方法的返回值是一个数组,所以需要拿数组来接收
        String[] strings= str.split(" ");//按照空格拆分
        for (String s:strings) {//使用for each遍历数组,打印数组里面的元素
            System.out.println(s);
        }
//split()方法:两个参数时,将字符串部分拆分,该数组长度就是limit极限
        String str1="abc de f";
        String[] strings1= str.split(" ",2);//拆分成两组
        for (String s:strings1) {//使用for each遍历数组,打印数组里面的元素
            System.out.println(s);
        }
    }
//打印结果:
abc
de
f
abc
de f
//拆分IP地址
        String str2="192.168.1.1";
        String[] strings2=str2.split("");//如果给一个空,不按照任何方式来拆分,就会默认将一个一个字符都拆开
        for (String s:strings2) {//使用for each遍历数组,打印数组里面的元素
            System.out.println(s);
        }
        String[] strings3=str2.split( " ");//如果给一个不匹配的字符,就不会拆开
        for (String s:strings3) {//使用for each遍历数组,打印数组里面的元素
            System.out.println(s);
        }
//打印结果:
1
9
2
.
1
6
8
.
1
.
1
192.168.1.1    

错误拆分代码示例:如果直接以点号拆分,在这里是错误的,会什么也不打印,为什么呢?

 String str2="192.168.1.1";  
 String[] strings4=str2.split( ".");
        for (String s:strings4) {//使用for each遍历数组,打印数组里面的元素
            System.out.println(s);
        }

通过split的源码可知,对于这些特殊的符号的处理,需要加双斜杠才可以进行字符串拆分。

image-20210927094440515

//拆分IP地址
        String str2="192.168.1.1";
        String[] strings5=str2.split( "\\.");//以点号拆分,加双斜杠才可以
        for (String s:strings5) {//使用for each遍历数组,打印数组里面的元素
            System.out.println(s);
        }
        String str3="192\\168\\1\\1";
        String[] strings6=str3.split( "\\\\");//用斜杠拆分,也要加双斜杠才可以
        for (String s:strings6) {
            System.out.println(s);
        }
        String str4="192*168*1*1";
        String[] strings7=str4.split( "\\*");//用*拆分,也要加双斜杠才可以
        for (String s:strings7) {
            System.out.println(s);
        }
//打印结果:
192
168
1
1
192
168
1
1
192
168
1
1

如何分割多次?

public static void main(String[] args) {
        //如何分割多次?
        String str = "name=zhangsan&age=18";
        String[] strings1 = str.split("&");//第一次分割:先以&进行分割
        for (String s1 : strings1) {
            String[] strings2 = s1.split("=");//第二次分割:让s1以=进行分割
            for (String s2 : strings2) {//遍历并打印s2
                System.out.println(s2);
            }
        }
    }
//打印结果:
name
zhangsan
age
18

△练习题:字符串连接

题目描述:借用任何字符串库函数实现无冗余的接受两个字符串,然后把他们无冗余的连接起来。

输入描述:每一行包括两个字符串,长度不超过100.

输出描述:可能有多组测试数据,对于每组数据,借用任何字符串库函数实现无冗余的接受两个字符串,然后把他们无冗余的连接起来。输出连接后的字符串。

import java.util.Scanner;
public class Main{
    public static String func(String str){//传参
        String[] strings=str.split(" ");//根据空格分割 
        String ret="";//将字符串拼接起来并放到ret中 
        for(String s:strings){//遍历数组
            ret+=s;
        }
        return ret;
    }
   public static void main(String[] args ){
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()){//加while可以实现读下一个
        String str=scan.nextLine();//这句代码每次只能读一行,把它放在循环里面,可以实现读下一个
        String ret=func(str);
        System.out.println(ret);
       }
   }
}
//打印结果:
abc de
abcde
字符串截取

从一个完整的字符串之中截取出部分内容。可用方法如下

NO方法名称类型描述
1public String substring(int beginIndex)普通从指定索取截取到结尾
2public String substring(int beginIndex,int endIndex)普通截取部分内容

查看帮助手册搜索String:image-20210927080622431

  public static void main(String[] args) {
        String str1="ababcabcd";
        //从指定索取截取到结尾,即给一个参数代表从这个位置开始截取到结束位置
        String ret= str1.substring(1);//substring的返回值是字符串,所以需要拿字符串来接收,1表示从1号位置开始截取
        System.out.println(ret);
        //截取部分内容
        String ret1=str1.substring(1,4);//左闭右开:[1,4)
        System.out.println(ret1);
    }

注意事项:

1.索引从0开始.

2.注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标.

其他操作方法
NO方法名称类型描述
1public String trim()普通去掉字符串中的左右空格,保留中间空格
2public String toUpperCase()普通字符串转大写
3public String toLowerCase()普通字符串转小写
4public native String intern()普通字符串入池操作
5public String concat(String str)普通字符串连接,等同于”+“,不入池
6public int length()普通取得字符串长度
7public boolean isEmpty()普通判断是否为空字符串,但不是null,而是长度为0

1️⃣trim()方法,去掉字符串中的左右空格,保留中间空格

public static void main(String[] args) {
        String str1="   aba   bacbcd     ";
        String ret= str1.trim();//trim的返回值是字符串,所以需要拿字符串来接收
        System.out.println(ret);
    }

2️⃣toUpperCase()方法,将字符串转大写

​ toLowerCase方法,将字符串转小写

代码示例:这两个方法只对字母有效

public static void main(String[] args) {
// toLowerCase()方法,将字符串转小写
        String str2="aBcDef巴";
        String ret1=str2.toLowerCase();
        System.out.println(ret1);
//toUpperCase()方法,将字符串转大写
        String ret2=str2.toUpperCase();
        System.out.println(ret2);
}
//打印结果:
abcdef巴
ABCDEF巴

3️⃣intern()方法,字符串入池操作

5️⃣ length()方法,取得字符串长度

public static void main(String[] args) { 
    String str2="aBcDef巴";
    String ret2=str2.toUpperCase();
    System.out.println(ret2.length());//注意:对于ret2来说,length()是方法
    int[] array={1,2,3,4,5};
    System.out.println(array.length);//注意:对于array来说,length是属性
    }

注意两个length的区别,数组长度使用数组名称.length属性,而String中使用的是length()方法

image-20210927170041740

6️⃣isEmpty()方法,判断是否为空字符串,但不是null,而是长度为0

 String string1="";//空串:表示里面什么都没有
 String string2=null;//表示指向了null对象
练习题1:首字母大写

String类并没有提供首字母大写操作,需要自己实现。

代码示例:

 public static void main(String[] args) {
        System.out.println(fistUpper("yuisama"));
        System.out.println(fistUpper(""));
        System.out.println(fistUpper("a"));
    }
    public static String fistUpper(String str) {
        if ("".equals(str)||str==null) {
            return str ;
        }
        if (str.length()>1) {
            return str.substring(0, 1).toUpperCase()+str.substring(1) ;
        }
        return str.toUpperCase() ;
    }
//打印结果:
Yuisama

A
练习题2:实现字符串逆置

库里面是没有让字符串逆置的方法的,需要自己手动实现。

代码示例:

 public static String reverse(String str,int begin,int end){//定义一个开始和结束参数
        char[]  value=str.toCharArray(); //先把字符串转换成字符数组
        while(begin<end){
            char tmp=value[begin];
            value[begin]=value[end];
            value[end]=tmp;
            begin++;
            end--;
        }
        //return new String(value);//第一种返回方式
        return String.copyValueOf(value);//第二种返回方式,将value数组变成是string类型了。
    }
    public static void main(String[] args) {
        String str="abcdefg";
        String ret= reverse(str,0,str.length()-1);//调用reverse,它的返回值是String,ret去接收
        System.out.println(ret);
    }
//打印结果:
gfedcba
练习题3:翻转字符串

题目描述:给一个字符类型的数组chas和一个整数size,请把大小为size的左半区整体右移到右半区,右半区整体移动到左边。

输入描述:输入两行,第一行一个整数,代表size,第二行一个字符串,代表chas

输出描述:输出一行字符串,代表翻转后的字符串。

输入

3

abcdefg

输出

defgabc

逻辑分析如图:

image-20210927210439737

代码示例:

import java.util.Scanner;
public class TestDemo3 {
    //逆置函数
    public static String reverse(String str, int begin, int end) {//定义一个开始和结束参数
        char[] value = str.toCharArray(); //先把字符串转换成字符数组
        while (begin < end) {
            char tmp = value[begin];
            value[begin] = value[end];
            value[end] = tmp;
            begin++;
            end--;
        }
        //return new String(value);//第一种返回方式
        return String.copyValueOf(value);//第二种返回方式,将value数组变成是string类型了。
    }
    public static String  func(String str, int n) {
        if(str==null || n<=0 || n>=str.length()){//判断参数不满足条件是,返回null
            return null;
        }
        str = reverse(str, 0, n - 1);//调用逆置函数reverse,第一次逆置(前半部分逆置):从0号位置开始到n-1号位置结束,保存到新的str
        str = reverse(str, n, str.length() - 1);//第二次逆置:在第一次逆置之后的结果上,逆置后半部分:从n号位置到str.length() - 1位置结束,并保存新的到str
        str = reverse(str, 0, str.length() - 1);//第三次逆置:最后进行整体的逆置,从0号位置开始到str.length() - 1位置结束,并保存新的到str
        return str;//返回值类型为String
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        String str = scanner.next();//nextInt()和nextLine()不能同时出现,所以只能写next()
        String ret = func(str, n);//调用func,返回值是String ,使ret接收
        System.out.println(ret);
    }
}
//打印结果:
4
abcdefghi
efghiabcd
StringBuffer 和 StringBuilder

首先来回顾下String类的特点:

  • 任何的字符串常量都是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指向而已。
  • 通常来讲String的操作比较简单,但是由于String的不可更改特性,为了方便字符串的修改,提供了StringBuffer和StringBuilder类。
  • StringBuffer 和 StringBuilder 大部分功能是相同的,这里主要介绍 StringBuffer
  • 在String中使用"+"来进行字符串连接,但是这个操作在StringBuffer类中需要更改为append()方法:
public static void main(String[] args) {
        //String的拼接用加号拼接,但会产生大量的临时对象(变量)
        String str="";
        for(int i=0;i<10;i++){
            str+='a';
        }
        System.out.println(str);
    }
 public static void main(String[] args) {
        //StringBuffer stringBuffer=new StringBuffer();//它是一个类
        StringBuilder stringBuilder=new StringBuilder();//它是一个类
        stringBuilder.append("abcd");
        stringBuilder.append("1234").append("cdef");
        //append返回的是this,即当前对象(stringBuffer)的引用。
        // stringBuilder的拼接用append()拼接,不会产生大量的临时对象(变量),它只维护了一份
    }

image-20210927232849825

 public static void main(String[] args) 
StringBuffer sb1=new StringBuffer();
        sb1.append("hello");
        sb1.reverse();
        System.out.println(sb1);

        StringBuffer sb2=new StringBuffer();
        sb1.append("hello");
        StringBuffer stringBuffer=sb2.reverse();
        System.out.println(stringBuffer);
}
//打印结果:
olleh
olleh

Stringbuilder和Stringbuffer的区别?

image-20210927232927359
面试题:请解释String、StringBuffer、StringBilder的区别?

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

StringBuffffer与StringBuilder大部分功能是相似的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值