【JavaSE】String类

news2025/1/22 13:07:56

目录

前言:

1.1、了解字符串构造方法

1.2、求字符串长度(xxx.length())

1.3、isEmpty()方法

1.4、String对象的比较 

 1.4.1、通过(str1 == str2)来比较,这样比较的是两个引用当中的地址

1.4.2、 boolean equals(Object anObject)方法:比较两个引用所指向的对象里面的内容是否一致

1.4.3、 int compareTo(String s)方法:用来比较两个字符串的大小

 1.4.4、int compareToIgnoreCase(String str)方法:与compareTo方式相同,但是忽略大小写,进行比较

1.5、字符串查找

1.5.1、char  charAt(int index)方法:查找index下标上的字符

1.5.2、int  indexOf(int ch)方法:找字符串中c第一次出现的位置,没有返回-1

 1.5.3、int  indexOf(int ch,int fromIndex)方法:从指定下标(fromIndex)开始查找字符c第一次出现的位置(下标)

1.5.4、 int indexOf(String str)方法:查找字符串中某一串字符串(abcd)出现的位置,返回这个字符串的第一个字母的下标,没有返回-1

 1.5.5、int lastIndexOf(int ch):默认从后往前找,找到返回下标,没找到返回-1

 1.5.6、int lastIndexOf(int ch, int fromIndex)方法:从指定位置(fromIndex)开始找,从后往前字母(a)第一次出现的位置。

1.6、字符串的转换

1.6.1、数字转字符串:xxx.valueOf()

1.6.2、字符串转数字 :Integer.paresInt(str1)

1.6.3、字符串小写转大写:xxx.toUpperCase();

 1.6.4、字符串大写转小写:xxx.toLoweCase();

 1.6.5、字符串转数组:xxx.toCharArray();

 1.6.6、格式化输出

1.7、字符串的替换

1.7.1、替换指定的字母:xxx.replace();

1.7.2、 替换所有指定的内容(xxx.replaceAll)

 1.7.3、替换首个所指的内容(xxx.replaceFirst)

 1.8、字符串的拆分

1.8.1、String[] split(String regex):将字符串全部拆分

1.8.2、 String[] split(String regex, int limit) :将字符串以指定的格式,拆分为limit组

1.8.3、拆分IP地址:有一些特殊字符作为分割符可能无法正常切分,需要加上转义。

1.8.4、多次拆分

 1.9、字符串的截取

1.9.1、String substring(int beginIndex) :从指定位置开始截取所有字符

 1.9.2、String substring(int beginIndex, int endIndex) :截取某个区域内的内容

 1.10、String trim():去掉字符串中的最外侧的空格,保留中间空格

 1.11、字符串的不可变性

 1.12、字符串的修改

2、StringBulider和StringBuffer 

2.1、StringBulider的学习

 2.1.1、StringBuilder类的append方法

 2.1.2、Stringbuilder类当中的方法介绍

 2.2、String、StringBuilder、StringBuffer的区别

2.3、来看一道面试题

2.4、习题


前言:

在c语言中,使用字符串,一般使用字符数组和字符串指针,它没有一个专门的类。而在Java中设计出专门的类,将数据和操作数据的方法放在一个类当中,这样符合Java的面向对象的思想。

🏆创建一个类对最终目的就是实例化对象,所以在学习一个类的时候一定是从它的构造方法开始学起。 


1.1、了解字符串构造方法

String类提供的构造方法有很多,常用的就一下三种:

1️⃣、使用常量串构造

2️⃣、直接newString对象

3️⃣、使用字符数组经行构造

public class Test {
    public static void main(String[] args) {
        //使用常量串构造
        String str1 = "hello";
        System.out.println(str1);
        //直接newString对象
        String str2 = new String("hello");
        System.out.println(str2);
    }
}

String类是引用类型所以这两种写法的本质是一样的区别就是使用常量串简化了直接newString对象。

public class Test {
    public static void main(String[] args) {
        //字符数组
        char[] values = {'a','v','c','d'};
        //这里new String对象,是调用构造方法,将字符数组转化成为字符串。
        String str3 = new String(values);
        System.out.println(str3);
    }
}

 当然,想了解String类更多的构造方法,可以选中String按住Ctrl+点击鼠标左键,然后再点击左下角的Structure,来查看String类的构造方法。

 ❗❗❗【注意】

1、String是引用数据类型,内部并不存储字符串本身,String类有两个成员属性,在创建String类的时候,不论调用有参还是无参构造方法,都会给value属性赋值。

🌈两个成员属性:value  hash

 2、通过调试上述的代码,我们可以看见,字符串结束的时候,并不像C语言一样,使用\0来结束。

 

 上述代码,可以画图理解:


String是一个类,那么就有很多方法,那么现在来了解一下他的方法

1.2、求字符串长度(xxx.length())

public class Test {
    public static void main(String[] args) {
        String str1 = "hello";
        System.out.println(str1.length());
        //通过调用String类当中的lenght()方法,就可以求出字符串的长度
    }

 相比于数组求长度(array.length)

public class Test {
    public static void main(String[] args) {
        int[] array = {1,2,3,4};
        System.out.println(array.length);
}

💥字符串求长度调用的是length()方法,而数组求长度调用的类似于一个属性(array.length),所以在使用的时候要分清是否要加()


1.3、isEmpty()方法

表示判断引用所指向的对象里面的字符串长度是否为0,是,返回true,不是,返回false。

public class Test {
    public static void main(String[] args) {
    String str2 = "";
    System.out.println(str2.length());//0
    //下面两个isEmpty表示的空,是字符串长度为空
    System.out.println(str2.isEmpty());//true
    //null:表示str3指向的引用为空,表示str3不指向任何对象
    String str3 = null;
}

❗❗❗注意:

在Java中“”引起来的也是String类型的对象

// 打印"hello"字符串(String对象)的长度
System.out.println("hello".length());

在调用上述两个方法时,一定是一个字符串类型,不一定是一个变量,它也可以是一个常量


1.4、String对象的比较 

字符串的比较有两种情况:

1️⃣相不相同

2️⃣大小

 1.4.1、通过(str1 == str2)来比较,这样比较的是两个引用当中的地址

public class Test {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "abcd";
        System.out.println(str1 == str2);
        //比较的是两个引用当中的地址,结果一定是错的
    }

1.4.2、 boolean equals(Object anObject)方法:比较两个引用所指向的对象里面的内容是否一致

public class Test {
    public static void main(String[] args) {
        String str1 =  new String("hello");
        String str2 =  new String("hello");
        System.out.println(str1.equals(str2));
    }

✨拓展:equals也可以忽略大小写进行比较内容是否一致

public class Test {   
    public static void main(String[] args) {
        String str1 =  new String("HEllo");
        String str2 =  new String("hello");
        //忽略大小写进行比较内容是否一致,返回true或false
        System.out.println(str1.equalsIgnoreCase(str2));
    }
}

1.4.3、 int compareTo(String s)方法:用来比较两个字符串的大小

compareTo()方法,按字典序进行比较大小

字典序:字符大小的顺序

public class Test {
    public static void main(String[] args) {
        String str1 =  new String("hello");
        String str2 =  new String("abcd");
        //比较两个引用所指向的对象的内容的大小
        System.out.println(str1.compareTo(str2));
    }

当str1>str2时,返回一个正数

当str1<str2时,返回一个负数

当str1=str2时,返回0

str1:调用这个方法的引用,str2:作为参数传给这个方法的引用

这里可以了解一下这个方法的返回值

所以上述代码,比较结果为7,h比a大7,返回了差值。

✨字符串比较存在这样的情况 

public class Test {
    public static void main(String[] args) {
        String str1 =  new String("helloabc");
        String str2 =  new String("hello");
        //比较两个引用所指向的对象的内容的大小
        System.out.println(str1.compareTo(str2));
    }

 

 1.4.4、int compareToIgnoreCase(String str)方法:与compareTo方式相同,但是忽略大小写,进行比较

public class Test {
    public static void main(String[] args) {
        String str1 =  new String("Hello");
        String str2 =  new String("hello");
        //忽略大小写进行比较
        System.out.println(str1.compareToIgnoreCase(str2));
    }


1.5、字符串查找

方法功能
char  charAt(int index)返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常
int  indexOf(int ch)返回ch第一次出现的位置,没有返回-1
int  indexOf(int ch,int fromIndex)从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str)返回str第一次出现的位置,没有返回-1
int indexOf(String str,int fromIndex)从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch)从后往前找,返回ch第一次出现的位置,没有返回-1
int  lastIndexOf(int ch,int fromIndex)从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1
int lastIndexOf(String str)从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str,int fromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1

1.5.1、char  charAt(int index)方法:查找index下标上的字符

public class Test {
    public static void main(String[] args) {
        String str1 = "hello";
        for (int i = 0; i < str1.length(); i++){
    //将变量i作为charAt()方法的参数,被charAt()方法的index参数接收,每循环一次输出一个字母
            System.out.println(str1.charAt(i));
        }
    }

1.5.2、int  indexOf(int ch)方法:找字符串中c第一次出现的位置,没有返回-1

public class Test {
    public static void main(String[] args) {
        String str1 = "abcabcabcabcde";
        //直接返回c字母在数组中的下标
        System.out.println(str1.indexOf('c'));
    }

 

 1.5.3、int  indexOf(int ch,int fromIndex)方法:从指定下标(fromIndex)开始查找字符c第一次出现的位置(下标)

public class Test {
    public static void main(String[] args) {
        String str1 = "abcabcabcabcde";
        //从指定的下标为6的位置开始找c第一次出现的位置(下标)
        System.out.println(str1.indexOf('c',6));
    }

1.5.4、 int indexOf(String str)方法:查找字符串中某一串字符串(abcd)出现的位置,返回这个字符串的第一个字母的下标,没有返回-1

public class Test {
    public static void main(String[] args) {
        String str1 = "abcabcabcabcde";
        System.out.println(str1.indexOf("abcd"));
    }
}

 1.5.5、int lastIndexOf(int ch):默认从后往前找,找到返回下标,没找到返回-1

public class Test {
    public static void main(String[] args) {
        String str1 = "abcabcabcabcde";
        //查找的时候,是从后往前找,但是返回下标的时候,是从前往后数
        System.out.println(str1.lastIndexOf('a'));
    }
}

 1.5.6、int lastIndexOf(int ch, int fromIndex)方法:从指定位置(fromIndex)开始找,从后往前字母(a)第一次出现的位置。

public class Test {
    public static void main(String[] args) {
        String str1 = "abcabcabcabcde";
        //查找的时候,是从后往前找,但是返回下标的时候,是从前往后数
        System.out.println(str1.lastIndexOf('a',7));
    }


1.6、字符串的转换

1.6.1、数字转字符串:xxx.valueOf()

public class Test{
     public static void main(String[] args) {
        //数字转字符串
         String str1 = String.valueOf(123);
         System.out.println(str1);
     }
}

1.6.2、字符串转数字 :Integer.paresInt(str1)

public class Test{
     public static void main(String[] args) {
         String str2 = "12345";
         //字符串转数字
         int data = Integer.parseInt(str2);
         System.out.println(data);
     }

 以上这两种转换只限定于数字样式的字符串,将字符串和数字之间相互转换,不能字母和数字之间转换,这样编译器会报错。

1.6.3、字符串小写转大写:xxx.toUpperCase();

public class Test{
     public static void main(String[] args) {
         String str1 = "abcd";
         //字符串小写转大写
         System.out.println(str1.toUpperCase());
     }

 1.6.4、字符串大写转小写:xxx.toLoweCase();

public class Test{
     public static void main(String[] args) {
         String str2 = "ABCD";
         //字符串大写转小写
         System.out.println(str2.toLowerCase());
     }

 1.6.5、字符串转数组:xxx.toCharArray();

public class Test{
     public static void main(String[] args) {
         String str1 = "abcdef";
        //字符串转数组,因为toCharArray()方法的返回值是char[]类型,所以用char[]类型的数组接收
         char[] array = str1.toCharArray();
         for (int i = 0; i < array.length; i++) {
             System.out.println(array[i]);
         }
     }
}

 1.6.6、格式化输出

 public class Test{
     public static void main(String[] args) {
         String s = String.format("%d-%d-%d",2022,12,25);
         System.out.println(s);
     }
}


1.7、字符串的替换

1.7.1、替换指定的字母:xxx.replace();

public class Test{
     public static void main(String[] args) {
         String str1 = "aaaaabbbbbddddcccc";
         //将字符串中的a字母全都替换成p
         String ret1 = str1.replace('a','p');
         System.out.println(ret1);
     }
}

1.7.2、 替换所有指定的内容(xxx.replaceAll)

public class Test{
     public static void main(String[] args) {
          String str2 = "abaababababcd";
          String ret2 = str2.replaceAll("ab","ooo");
          System.out.println(ret2);
     }
}

 1.7.3、替换首个所指的内容(xxx.replaceFirst)

public class Test{
     public static void main(String[] args) {
           String str1 = "aaaaabbbbbddddcccc";
           String ret3 = str1.replaceFirst("ab","999");
           System.out.println(ret3);
     }
}

✨ 拓展:上述的replaceAllreplaceFirst方法,也可以将字符串中的某个字符替换成空格,还是某些字符都是可以的。但是replace方法是不能实现

public class Test{
     public static void main(String[] args) {
           String str1 = "aaaaabbbbbddddcccc";
           String ret3 = str1.replaceFirst("ab"," # ");
           System.out.println(ret3);
     }
}

 

🎉🎉总结:由于字符串是不可变对象,所以上述的字符串的替换字符串的转化都没有修改当前的字符串,而是产生一个新的字符串,对其进行修改。 


 1.8、字符串的拆分

字符串的拆分有两种方法:

1.8.1、String[] split(String regex):将字符串全部拆分

public class Test{
     public static void main(String[] args) {
         String str = "how are you";
        //按空格拆分,将拆分后的字符串用字符串数组进行接收
         String[] strs = str.split(" ");
         for (int i = 0; i < strs.length; i++) {
             System.out.println(strs[i]);
         }
     }
}

1.8.2、 String[] split(String regex, int limit) :将字符串以指定的格式,拆分为limit组

public class Test{
     public static void main(String[] args) {
         String str = "how are you";
        //按照空格拆分,拆分成两组
         String[] strs = str.split(" ",2);
         for (int i = 0; i < strs.length; i++) {
             System.out.println(strs[i]);
         }
     }

1.8.3、拆分IP地址:有一些特殊字符作为分割符可能无法正常切分,需要加上转义。

 【注意事项】

  1. 字符"|" ,"*","+"都得加上转义字符,前面加上"\\".
  2. 而如果"\",那么就得写成"\\\\".
  3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符。

1、 

public class Test{
     public static void main(String[] args) {
         String str = "192.168.1.1";
        //按照.拆分,要添加转义字符\,但是这里添加了两个\,原因在于先将\转义,在转义.
         String[] strs = str.split("\\.");
         for (int i = 0; i < strs.length; i++) {
             System.out.println(strs[i]);
         }
     }

 2、

public class Test{
     public static void main(String[] args) {
         String str = "192\\168\\1\\1";
        //在写字符串的时候,不能单独写一个\,因为这样和后面的数组形成了转义必须写\\
        //按照\拆分,在写的时候,先要将\转义,再转义\\,所以这里就要写\\\\
         String[] strs = str.split("\\\\",2);
         for (int i = 0; i < strs.length; i++) {
             System.out.println(strs[i]);
         }
     }

 3、

public class Test{
     public static void main(String[] args) {
         String str = "192&168@1=1";
        //字符串被多个分割符隔开,想要将字符串按照这些分割符拆分,那么可以使用连字符将这些分隔符写在一起
         String[] strs = str.split("&|@|=");
         for (int i = 0; i < strs.length; i++) {
             System.out.println(strs[i]);
         }
     }
}

 

1.8.4、多次拆分

 public class Test{
     public static void main(String[] args) {
         String str = "name=zhangsan&age=18";
        //这个字符串中有两部分,名字和年龄,先将她两拆分
         String[] strs = str.split("&");
         for (int i = 0; i < strs.length; i++) {
            //拆分成两个数组后,再用=拆分
            String[] string = strs[i].split("=");
            for (String s:string){
                System.out.println(s);
            }
         }
     }
}

 1.9、字符串的截取

1.9.1、String substring(int beginIndex) :从指定位置开始截取所有字符

public class Test{
     public static void main(String[] args) {
        String str = "abcdefgh";
        //从第二个字母开始截取后面所有字母
        String s = str .substring(2);
         System.out.println(s);
     }

 1.9.2、String substring(int beginIndex, int endIndex) :截取某个区域内的内容

public class Test{
     public static void main(String[] args) {
        String str = "abcdefgh";
        //表示包含0下标的字符,不包含6下标的字符
        String s = str .substring(0,6);//他是一个前闭后开区间的写法[)
         System.out.println(s);
     }
}

注意事项:

1、索引从0开始

2、注意前闭后开区间的写法。

3、 字符串的拆分和截取,都不是再原字符串上操作的,都是在新产生的字符串上操作的。


 1.10、String trim():去掉字符串中的最外侧的空格,保留中间空格

public class Test{
     public static void main(String[] args) {
         String str = "   hello  abcd    ";
         System.out.println(str);
        //去掉最外侧的空格,保留中间的空格
         String ret = str.trim();
         System.out.println(ret);
     }
}


 1.11、字符串的不可变性

 public class Test{
     public static void main(String[] args) {
         String str1 = "abcd";
         String str2 = new String("abcd");
         String str3 = "abcd";
         System.out.println(str1 == str2);
         System.out.println(str1 == str3);
     }

 

 ❗❗❗【纠正错误】

上述这副图在这里只是用作理解上述代码中为什么str1==str3,字符串常量池还没有讲解,所以这幅图是错误的,举例来说

1、String str1 = "abc";从下面这副图来看,他创建了一个String对象(value)和一个char数组对象(abc).

 2、String str2 = new String(abc);从下面的图来看,它创建了两个String对象(value)和一个char数组对象(abc);

 这里涉及到常量池的概念,小编还没学习常量池的内容,所以这里就不讲解了。

 字符串为什么有不可变性?

  1. 给String类的引用赋值字符串后,在内存中字符串是以字符数组的形式保存的。
  2. String类当中的value[ ] 属性,是被private修饰的,也就是说value[ ] 是被封装的。
  3. 被封装了之后,因该要设置公开方法get和set方法,来得到value[ ] ,并且可以修改value[ ]所指向的数组中的值。
  4. 但是在String类当中,并没有给出公开的方法让我们得到value[ ]属性。得不到value[ ]引用,所以他指向的数组中的内容不能被修改,所以字符串具有不可变性 。

总结:

1、String类被final修饰,表明该类不能被继承

2、value被final修饰,表明value不能引用其他对象(指向不可变),即不能引用其他字符数组,但是其引用空间中的内容可以修改。

为什么String要设计成不可变的?(不可变对象的好处是什么?)

  1. 方便实现字符串池,如果String可变,那么对象池就需要考虑写时拷贝的问题了。
  2. 不可变对象是线程安全的。
  3. 不可变对象更方便缓存hash code,作为key时可以更高效的保存到HashMap中

 1.12、字符串的修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。

public class Test {
    public static void main(String[] args) {
        String str = "hello";
        str += "abc";
        System.out.println(str);
    }
}

通过反汇编来看一下,这种方式在中间创建了很多对象

 模拟一下上述反汇编的代码:

public class Test {

    public static void main(String[] args) {
            String str = "hello";
//        这里4句代码相当于上面代码的str += "abc";
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(str);
            stringBuilder.append("abc");
//        这里调用toString方法的作用是,在拼接完成之后,有一个新的String对象
            str = stringBuilder.toString();
            System.out.println(str);
    }
}

那么设想一下,每拼接一次,调用上述的4句代码,那么在代码编写时,写一个循环,那么每循环一次,调用这4句代码,就造成了代码效率非常低下。

总结

所以在循环当中不建议使用+对字符串进行拼接。因为这样的写法,会产生很多的临时对象,造成代码效率低下如果要修改建议尽量使用StringBuffer或者StringBulider


2、StringBulider和StringBuffer 

2.1、StringBulider的学习

由于String的不可更改特性,为了方便字符串的修改,Java中有提供了StringBulider和StringBuffer类这两个类大部分功能时相同的 

  通过上述图片可以看见,StringBuilder类有即有参构造方法,也有无参构造方法

 2.1.1、StringBuilder类的append方法

❓❓那么StringBuilder类对字符串进行拼接,会是什么样的那?

🕖先来看一下append方法的源码:

 🕕利用append方法对字符串进行拼接

public class Test {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("abc");
        System.out.println(stringBuilder);
        stringBuilder.append("123").append(10);
        stringBuilder.append(19.0);
        System.out.println(stringBuilder);//此时不会产生多余的临时对象,
//他永远返回的是当前对象,所有的修改都在当前对象
    }
}

 2.1.2、Stringbuilder类当中的方法介绍

方法说明
StringBuff append(String  str)在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、
double、float、int、long、Object、String、StringBuff的变量
char charAt(int index)获取index位置的字符
int length()获取字符串的长度
int capacity()获取底层保存字符串空间总的大小
void ensureCapacity(int
mininmumCapacity)
扩容
void setCharAt(int index,
char ch)
将index位置的字符设置为ch
int indexOf(String str) 返回str第一次出现的位置
int indexOf(String str, int
fromIndex)
从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str)返回最后一次出现str的位置
int lastIndexOf(String str,
int fromIndex)
从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(int
offset, String str)
在offset位置插入:八种基类类型 & String类型 & Object类型数据 
StringBuffer
deleteCharAt(int index)
删除index位置字符
StringBuffer delete(int
start, int end)
删除[start, end)区间内的字符
StringBuffer replace(int
start, int end, String str)
将[start, end)位置的字符替换为str
String substring(int start)从start开始一直到末尾的字符以String的方式返回
String substring(int
start,int end)
将[start, end)范围内的字符以String的方式返回
StringBuffer reverse()反转字符串
String toString() 将所有字符按照String的方式返回

 ❗❗❗总结:从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改频繁修改字符串可以考虑使用StringBuilder

❗❕❗注意:String和StringBuilder类不能直接转换。如果想要相互转换,可以采用如下原则:

  • String变为StringBuilder:利用StringBuilder的构造方法或append()方法。
  • StringBuilder变为String:调用toString()方法。
 //通过stringBuilder来调用toString方法,达到将StringBuilder类型对象转换为String类型对象
public class Test {
     public static void main(String[] args) {
           StringBuilder stringBuilder = new StringBuilder("abc");
           String ret = stringBuilder.toString();
    }
}
//通过stringBuilder调用构造方法或者append()方法,将String类型转换为StringBuilder类型
public class Test {
    public static void main3(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("abc");
        System.out.println(stringBuilder);
        stringBuilder.append("123");
        System.out.println(stringBuilder);
    }
}

 2.2、String、StringBuilder、StringBuffer的区别

  • String的内容不可修改,StringBuffer与StringBuilder的内容可以修改。
  • StringBuffer与StringBuilder大部分功能是相似的
  • StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

2.3、来看一道面试题

以下两串代码分别创建了几个String对象【前提:不考虑常量池之前是否存在】

String str = new String("ab");  // 会创建多少个对象
String str = new String("a") + new String("b");  // 会创建多少个对象

1️⃣第一句:创建了2个对象。

  1. 因为字符串是一个对象,
  2. 而又new了一个对象,所以有两个对象。

2️⃣第二句:创建了5个对象。

  1. 因为字符串是一个对象,
  2. 而又new了两个对象,
  3. 又因为在进行字符串的拼接,这样会创建一个StringBuilder类型的对象,
  4. 在拼接完成之后,又会通过StringBuilder类型的对象调用toString方法,这样又创建了一个String对象。
  5. 又因为问的是创建了几个String对象,所以StringBuilder对象在这里就不算了。
  6. 为什么StringBuilder调用的toString方法创建的对象在这里可以算一个String对象?toString方法创建的对象是String类型的,所以在这里算。

 


2.4、习题

1、字符串中的第一个唯一字符

给定一个字符串s,找到他的第一个不重复的字符,并返回他的索引。如果不存在,则返回-1。

要求:字符串s只包含小写字母。

public class Test {
    public int firstUniqChar(String s) {
        int[] count = new int[26];
        //统计每个字符出现的次数
        for(int i = 0; i < s.length(); ++i){
            char ch = s.charAt(i);
            count[ch - 'a']++;
        }
        //找第一个只出现一次的字符
        for(int i = 0; i < s.length(); ++i){
            char ch = s.charAt(i);
//通过for循环遍历,并且通过if判断每一个字母在上一轮的fou循环中计数的情况(是否只出现过一次,若第一个字母计数>1,那么就判断下一个字母,直到找到计数为一的字母,并返回该字母)
            if(count[ch - 'a'] == 1){//用ch - 'a'用字母的ASCII的减去97,得到字母在数组中的下标。
                return i;
            }
        }
        return -1;
    }

2、最后一个单词的长度

输出一个正数,表示输入字符串最后一个单词的长度。

import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNextLine()){
            String str = in.nextLine();
            int index = str.lastIndexOf(" ");//最后一个空格开始
            String ret = str.substring(index+1);//从最后一个空格+1的位置开始,向后计算字符串的长度
            System.out.println(ret.length());
        }
    }
}

3、检测一个字符串是否为回文字符串

如果在将所有大写字符转换为小写字符,并移除所有非字母数字字符之后短语正着读和反着读都一样。则可认为该短语是一个回文串。

字母和数字都属于数字字符。

要求 :给你一个字符串s,如果他是回文串,返回true;否则,返回false.

public class Test {
     public boolean isPalindrome(String s){
        s = s.toLowerCase();//将大写字母转换为小写
        int left = 0;//从左边开始的下标
        int right = s.length()-1;//从右边开始的下标
        while(left < right){
            while(left < right && !isValidChar(s.charAt(left))){
                left++;
            }
            while(left < right && !isValidChar(s.charAt(right))){//条件是左边下标小于右边下标,并且来两边要是有效字符。
                right -- ;
            }
            //判断如果左边字母不等于右边字母,返回false,两边字母相等,左边向前挪一位,右边向前挪一位。
            //每个字母判断完成之后,都相等,返回true。
            if(s.charAt(left) !=s.charAt(right)){
                return false;
            }else{
                left++;
                right--;
            }
        }
        return true;
    }
    //判断他是否为有效字符
    private boolean isValidChar(char ch){
        if(ch >= '0' && ch <= '9'|| ch <= 'a'&& ch <= 'z'){
        //上边语句可以优化为
        //if(Character.isDigit(ch)||Character.isLetter(ch))
        //isDigit()判断是否为数字  isLetter()判断是否为字母
            return true;
        }
        return false;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ONE·C++ || vector (一)】

总言 学习笔记&#xff0c;慢慢补充。 文章目录总言1、整体介绍&#xff1a;2、常用各种接口介绍2.1、vector的基本结构&#xff1a;构造、析构、赋值2.1.1、总体情况预览2.1.2、各项函数使用演示2.2、vector增删查改相关2.2.1、增删查改总览2.2.2、如何在vector中插入、删除、…

Kotlin之使用协程编写高效的并发程序

文章目录1.协程的基本用法2.更多的作用域构建器3.使用协程简化回调的写法协程属于Kotlin中非常有特色的一项技术&#xff0c;因为大部分编程语言中是没有协程这个概念的。那么什么是协程呢&#xff1f;它其实和线程有点相似&#xff0c;可以简单地将它理解成一种轻量级的线程。…

Linux学习入门

1、Linux简介 操作系统分类&#xff1a;桌面操作系统、、服务器操作系统、移动端操作系统、嵌入式操作系统桌面操作系统主要针对个人电脑&#xff0c;Linux在桌面操作系统的应用主要有国产操作系统&#xff0c;Ubuntu。服务器操作系统有windows和linux以及苹果&#xff0c;主流…

微信小程序是如何实现快速编译的?

过往中小企业或技术团队开发一个 App 的时间成本和人力成本居高难下&#xff0c;但是随着微信上线小程序&#xff0c;更像是为这部分群体打开了一扇天窗&#xff0c;此后小程序呈现出井喷式发展的状态&#xff0c;不仅微信&#xff0c;支付宝、百度、抖音等超级 App 都跟上步伐…

线程进阶

常见的锁策略乐观锁 vs 悲观锁乐观锁&#xff1a;预测锁竞争不是很激烈悲观锁&#xff1a;预测锁竞争会很激烈轻量级锁 vs 重量级锁轻量级锁加锁解锁开销比较小&#xff0c;效率更高重量级锁加锁解锁开销比较大&#xff0c;效率更低多数情况下&#xff0c;乐观锁&#xff0c;也…

在CSDN年收入竟达五位数?----大学生技术自媒体成长之路

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 还有不到两周就要过年了&#xff0c;自己也马上迈入了21岁&#xff0c;感慨时间飞快&#xff0c;从19岁开始入驻C站&#xff0c;到现在也已经整整两年了&#xff0c;把自己最好的两年青春时光留在了CSDN&#xff0c;超百万…

定义输出格式的使用-printf()函数

目录&#x1f4d6;printf()函数简介格式化规定符格式控制特殊规定字符示例printf()函数简介 printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息。 printf()函数的调用格式为:printf("<格式化字符串>", <参量表>);这里看输出很简…

Lua入门学习

一、初识Lua脚本 Lua 是一种轻量小巧的脚本语言&#xff0c;用标准C语言编写并以源代码形式开放&#xff0c; 其设计目的是为了嵌入应用程序中&#xff0c;从而为应用程序提供灵活的扩展和定制功能。官网&#xff1a;https://www.lua.org/ 1、HelloWorld CentOS7默认已经安装…

什么是docker

文章目录简介Docker 架构特性局限Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c…

〖产品思维训练白宝书 - 产品思维认知篇⑨〗- 像 产品经理 一样去思考解决问题

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…

数据结构:算法的初步认识

算法是解决特定问题求解步骤的描述&#xff0c;在计算机中表现为指令的有限序列&#xff0c;并且每条指令表示一个或多个操作。 什么是算法 要求你写一个求 123…100 结果的程序&#xff0c;你应该怎么写呢? 大多数人会马上写出下面的C语言代码(或者其他语言的代码): int a,…

seata的AT模式

seata 分布式事务解决方案 官网 &#xff1a; seata.io 事务模式&#xff1a; 名词 TC &#xff1a; transaction coordinator 事务协调者 维护全局事务 和 分支事务的状态&#xff0c;驱动全局事务提交或者回滚TM &#xff1a; transaction manager 事务管理器 定义全局事…

(考研湖科大教书匠计算机网络)第一章概述-第三节:计算机网络的定义、功能分类

文章目录一&#xff1a;计算机网络的定义&#xff08;1&#xff09;最简单定义&#xff08;2&#xff09;较好定义二&#xff1a;计算机网络功能三&#xff1a;计算机网络的分类&#xff08;1&#xff09;按照“覆盖范围”分类&#xff08;2&#xff09;按照“使用者”分类&…

【Linux学习】进程控制

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 在前面&#xff0c;我们学习了进程的相关概念&#xff0c;在这里本喵会给大家介绍如何控制进程。…

私人影院微信小程序源码,采用腾讯小程序云开发,包括影院动态,最新影讯,房间预约,后台预约管理,导出预约表格Excel数据等功能

功能介绍 私人影院是很多年轻人比较喜欢的地方&#xff0c;虽然空间小&#xff0c;但是他们喜欢在这样的空间里享受休闲的时光&#xff0c;通过提前预约订位&#xff0c;可以使商家和消费者节省时间&#xff0c;减少人力成本&#xff0c;大大方便业务的拓展&#xff0c;同时也…

Word控件Spire.Doc 【Table】教程(4):如何在C#、VB.NET中设置Word表格样式

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

备战蓝桥杯数学基础:位运算理论

[TOC](目录)位运算概述位运算就是基于整数的二进制表示进行的运算&#xff0c;由于计算机内部就是以二进制来村塾数据&#xff0c;位运算是相当快的。基本的位运算共6种&#xff0c;分别为按位与、按位或、按位异或、按位取反、左移和右移与、或、异或这三者都是两数间的运算&a…

【算法刷题】栈与队列题型及方法归纳

栈与队列的特点 1、栈&#xff1a;FIFO 栈是仅能对其一端进行操作的结构&#xff0c;实现后进先出的效果。在C中采用容器适配器的方式实现栈。&#xff08;容器适配器实际上就是对某一类型的对象进行泛化&#xff0c;定义了这一类泛化对象的可进行操作的逻辑&#xff09; 什么…

上半年要写的博客文章22

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

极端尺度物体的显著性分割方法(SOD 新 SOTA)

Paper Link&#xff1a;http://cvteam.buaa.edu.cn/papers.htmlBackground&#xff1a;显著性物体分割在常规图像场景取得突破进展&#xff0c;在极端尺度物体场景仍面临挑战。图像前景物体分割是深度学习、计算机视觉等领域的研究热点&#xff0c;在机器视觉、智能交通、智慧医…