【JavaSE】String

【本节目标】
1. 认识 String
2. 了解 String 类的基本用法
3. 熟练掌握 String 类的常见操作
4. 认识字符串常量池
5. 认识 StringBuffer StringBuilder

一、String类的重要性

        在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字符串应用又非常广泛,因此Java语言专门提供了String类。

           而且在面试中也频繁被问到,比如: String StringBuff StringBulider 之间的区别等。
  • 与C语言不同,C语言中字符串是以"\0"结尾的,也就是说这是它的结束标志
  • 但Java中并不以"\0"结尾,有它本身的判断结束方法

二.常用方法

1 字符串构造

String 类提供的构造方式非常多,常用的就以下三种:
  • 1.使用常量串构造
  • 2.直接newString对象
  • 3.使用字符数组进行构造
        String string1="hello";
        String string2=new String("world");
        char[] value={'a','b','c'};
        String string3=new String(value);
其他方法需要用到时,大家参考 Java 在线文档
注意
1. String 是引用类型,内部并不存储字符串本身 ,在 String 类的实现源码中, String 类实例变量如下:
public static void main(String[] args) {
// s1和s2引用的是不同对象 s1和s3引用的是同一对象
    String s1 = new String("hello");
    String s2 = new String("world");
    String s3 = s1;
    System.out.println(s1.length()); // 获取字符串长度---输出5
    System.out.println(s1.isEmpty()); // 如果字符串长度为0,返回true,否则返回false
}

 

2. Java“”引起来的也是String类型对象。

2 String对象的比较

字符串的比较是常见操作之一,比如:字符串排序。 Java 中总共提供了 4 中方式:

(1)==比较是否引用同一个对象

注意:对于内置类型, == 比较的是变量中的值;对于引用类型 == 比较的是引用中的地址。
public class Test {
    public static void main(String[] args) {
        String string1="hello";
        String string2=new String("world");
        char[] value={'a','b','c'};
        String string3=new String(value);
        String string4=string1;
        String string5="hello";
        System.out.println(string1==string4);
        System.out.println(string1==string2);
    }
}

(2)boolean equals

(Object anObject) 方法: 按照字典序比较
字典序:字符大小的顺序
        String类重写了父类 Object equals 方法, Object equals 默认按照 == 比较, String 重写 equals 方法后,按照如下规则进行比较,比如: s1.equals(s2)

 

(3)int compareTo(String s)

方法 : 按照字典序进行比较
equals 不同的是, equals 返回的是 boolean 类型,而 compareTo 返回的是 int 类型。具体比较方式:
1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
2. 如果前 k 个字符相等 (k 为两个字符长度最小值 ) ,返回值两个字符串长度差值

  public static void main(String[] args) {
        String string1=new String("world");
        String string2=new String("abcdef");
        String string3=new String("abcdef");
        String string4=new String("abcdefg");
        System.out.println(string2.compareTo(string1));
        System.out.println(string2.compareTo(string4));
        System.out.println(string2.compareTo(string3));
        System.out.println(string1.compareTo(string3));
    }

(4)int compareToIgnoreCase(String str)

方法:与 compareTo 方式相同,但是忽略大小写比较

    public static void main(String[] args) {
        String string1=new String("Abcdef");
        String string3=new String("abcdef");
        System.out.println(string1.compareTo(string2));
        System.out.println(string1.compareToIgnoreCase(string2));
    }

3 字符串查找

字符串查找也是字符串中非常常见的操作, String 类提供的常用查找的方法:

方法

功能

char charAt(int index)

返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常

int indexOf(int ch)

返回ch第一次出现的位置,没有返回-1 

int indexOf(int ch, int fromlndex)

从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)char charAt(int index)

   public static void main(String[] args) {
        String s1="hello";
        char c=s1.charAt(0);
        System.out.println(c);
    }

(2)int indexOf(int ch)+int indexOf(int ch, int fromlndex)

    public static void main(String[] args) {
        String s1="hello";
        int index=s1.indexOf('l');
        int index2=s1.indexOf('l',3);
        System.out.println(index);
        System.out.println(index2);
    }

(3)int indexOf(String str)

    public static void main(String[] args) {
        String s1="hello";
        int index3=s1.indexOf("ll");
        System.out.println(index3);
    }

(4)int indexOf(String str, int fromindex)

    public static void main(String[] args) {
        String s1="hello";
        int index3=s1.indexOf("ll",3);
        System.out.println(index3);
    }

tip:后四个方法与前四个基本相同,不再演示

4 转化

(1)数值和字符串转化

该方法是一个静态方法,用类名.方法名

        String s1=String.valueOf(1234);
        String s2=String.valueOf(12.34);
        int i=Integer.parseInt(s1);
        double d=Double.parseDouble(s2);   

(2)大小写转换

    public static void main(String[] args) {
        String s1="hello";
        String s2=s1.toUpperCase();
        System.out.println(s2);
    }



    public static void main(String[] args) {
        String s1="hello";
        String s2=s1.toUpperCase();
        String s3=s2.toLowerCase();
        System.out.println(s3);
    }

(3)字符串转数组

    public static void main(String[] args) {
        String s = "hello";
// 字符串转数组
        char[] ch = s.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            System.out.print(ch[i]);
        }
        System.out.println();
// 数组转字符串
        String s2 = new String(ch);
        System.out.println(s2);
    }

(4)格式化

    public static void main(String[] args) {
        String S=String.format("%d-%d-%d",2024,9,27);
        System.out.println(S);
    }

5 字符串替换

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

代码演示:

    public static void main(String[] args) {
        String s="aaaaaaaaaabbbbbbbbbbbb";
        String S1=s.replace('a','k');
        String S2=s.replaceFirst("a","k");
        System.out.println(S1);
        System.out.println(S2);
    }

6 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
可用方法如下:

方法

功能

String[] split(String regex)

将字符串全部拆分

String[]split(String regex, int limit)

将字符串以指定的格式,拆分为limit组

 (1)String[] split(String regex)

    public static void main(String[] args) {
        String s1="name=sherry&age=20";
        String[] strings=s1.split("&");
        for (String s:strings) {
            System.out.println(s);
        }
    }

 (2)String[]split(String regex, int limit)

    public static void main(String[] args) {
        String s1="name=sherry&age=20";
        String s2="hello world I love you";
        String[] strings=s1.split("&");
        String[] strings2=s2.split(" ",2);
        for (String s:strings2) {
            System.out.println(s);
        }
    }
注意事项 :
1. 字符 "|","*","+" 都得加上转义字符,前面加上 "\\" .
2. 而如果是 "\" ,那么就得写成 "\\\\" .
3. 如果一个字符串中有多个分隔符,可以用 "|" 作为连字符 .
 String str = "192.168.1.1" ;
    String[] result = str.split("\\.") ;
    for(String s: result) {
        System.out.println(s);
        }
    public static void main(String[] args) {
        String s1="name=sherry&age=20";
        String[] strings=s1.split("&|=");
        for (String S:strings) {
            System.out.println(S);
        }
    }

 (3)多次拆分

    public static void main(String[] args) {
        String s1="name=sherry&age=20";
        String[] strings=s1.split("&");
        for (int i = 0; i < strings.length; i++) {
            String[] strings2=strings[i].split("=");
            for (String S:strings2) {
                System.out.println(S);
            }
        }
    }

7 字符串截取 

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

方法

功能

String substring(int beginindex)

从指定索引截取到结尾

String substring(int beginindex, int endlndex)

截取部分内容

代码示例: 观察字符串截取

    public static void main(String[] args) {
        String s="abcdefg";
        String sub=s.substring(2,5);
        System.out.println(sub);
    }

注意事项:

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

8 其他操作方法

 

String trim()

    public static void main(String[] args) {
        String s="     a   b    cde    f      ";
        String ss=s.trim();
        System.out.println(ss);
    }

9 字符串的不可变性  

String 是一种不可变对象 . 字符串中的内容是不可改变。字符串不可被修改,是因为:
1. String 类在设计时就是不可改变的, String 类实现描述中已经说明了
以下来自 JDK1.8 String 类的部分实现
String 类中的字符实际保存在内部维护的 value 字符数组中 ,该图还可以看出:
  • 1. String类被final修饰,表明该类不能被继承
  • 2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。
2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象。
比如 replace 方法
纠正 】网上有些人说:字符串不可变是因为其内部保存字符的数组被 final 修饰了,因此不能改变。
这种说法是错误的,不是因为 String 类自身,或者其内部 value final 修饰而不能被修改。
final 修饰类表明该类不想被继承, final 修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内 容是可以修改的
public static void main(String[] args) {
    final int array[] = {1,2,3,4,5};
    array[0] = 100;
    System.out.println(Arrays.toString(array));
    // array = new int[]{4,5,6}; // 编译报错:Error:(19, 9) java: 无法为最终变量array分配值
}

为什么 String 要设计成不可变的 ? ( 不可变对象的好处是什么 ?) ( 选学 )
1. 方便实现字符串对象池 . 如果 String 可变 , 那么对象池就需要考虑写时拷贝的问题了 .
2. 不可变对象是线程安全的 .
3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap .
那如果想要修改字符串中内容,该如何操作呢?

10 字符串修改

注意:尽量避免直接对 String 类型对象进行修改,因为 String 类是不能修改的,所有的修改都会创建新对象,效率 非常低下。
   public static void main(String[] args) {
        String s = "hello";
        s += " world";
        System.out.println(s); // 输出:hello world
    }
 一般来说string+=和利用 StringBuffer 或者 StringBuilder没什么区别。
    public static void main(String[] args) {
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("hello");
        stringBuilder.append(" world");
        String s=stringBuilder.toString();
        System.out.println(s);
    }
    public static void main13(String[] args) {
        String s1="hello";
        s1+="  world";
        System.out.println(s1);
    }

但是string+=这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。

        可以看待在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder

b. 借助 StringBuffer StringBuilder

三. StringBuilderStringBuffer

1 StringBuilder的介绍

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

方法

说明

StringBuff append(Stringstr)

在尾部追加,相当于String的+=,可以追加:boolean、char、char[l.double、float、int、long、Object、String、StringBuff的变量

char charAt(int index)

获取index位置的字符

int length()

获取字符串的长度

int capacity()

获取底层保存字符串空间总的大小

void ensureCapacity(intmininmumCapacity)

扩容

void setCharAt(int index,char ch)

将index位置的字符设置为ch

int indexOf(String str)

返回str第一次出现的位置

int indexOf(String str, intfromIndex)

从fromIndex位置开始查找str第一次出现的位置

int lastindexOf(String str)

返回最后一次出现stt的位置

int lastIndexOf(String str,int fromIndex)

从fromtindex位置开始找str最后一次出现的位置

StringBuff insert(intoffset, String str)

在offset位置插入:八种基类类型 & String类型 & Object类型数据

StringBufferdeleteCharAt(int index)

删除index位置字符

StringBuffer delete(intstart, int end)

删除[start, end)区间内的字符

StringBuffer replace(intstart, int end, String str)

将[start,end)位置的字符替换为str

String substring(int start)

从start开始一直到未尾的字符以String的方式返回

String substring(intstart, int end)

将[start,end)范围内的字符以String的方式返回

StringBuffer reverse()

反转字符串

String toString()

将所有字符按照String的方式返回

从上述例子可以看出: String StringBuilder 最大的区别在于 String 的内容无法修改,而 StringBuilder 的内容可 以修改 。频繁修改字符串的情况考虑使用 StringBuilder
注意: String StringBuilder 类不能直接转换。如果要想互相转换,可以采用如下原则 :
  • String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
  • StringBuilder变为String: 调用toString()方法。
3.2 面试题:
1. String StringBuffer StringBuilder 的区别
  • String的内容不可修改,StringBufferStringBuilder的内容可以修改.
  • StringBufferStringBuilder大部分功能是相似的
  • StringBuffer采用同步处理,,一般用于多线程,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
2. 以下总共创建了多少个 String 对象【前提不考虑常量池之前是否存在】
String str = new String ( "ab" ); // 会创建多少个对象
String str = new String ( "a" ) + new String ( "b" ); // 会创建多少个对象

四. Stringoj

1. 第一个只出现一次的字符

class Solution {
    public int firstUniqChar(String s) {
        int[] count=new int[26];
        int pos=-1;
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            count[ch-'a']++;
        }
        for(int j=0;j<s.length();j++){
            int k=s.charAt(j)-'a';
            if(count[k]==1){
                pos=j;
                break;
            }
        }
        return pos;
    }
}

 2. 最后一个单词的长度

采用split方法

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String string=in.nextLine();
        String[] s=string.split(" ");
        String ss=s[s.length-1];
        System.out.println(ss.length());
        }
    }

不采用spli方法

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String string=in.nextLine();
        int count=0;
        for(int i=string.length()-1;i>=0;i--){
            if(string.charAt(i)==' '){
                break;
            }
            count++;
        }
        System.out.println(count);
        }
    }

3. 检测字符串是否为回文

class Solution {
    public static boolean isLegal(char ch){
        boolean flag=false;
        if(ch>='a'&&ch<='z'){
            flag=true;
        }else if(ch>='0'&&ch<='9'){
            flag=true;
        }
        return flag;
    }
    public boolean isPalindrome(String s) {
        String string=s.toLowerCase();
        int left=0;
        int right=string.length()-1;
        while(left<right){
            while(left<right && (isLegal(string.charAt(left))==false)){
                left++;
            }
             while(left<right && (isLegal(string.charAt(right))==false)){
                right--;
            }
            if(string.charAt(left)==string.charAt(right)){
                left++;
                right--;
            }else{
                return false;
            }
        }
         return true;

    }
}

Tip:在这个过程中,我了解了判断是不是数字和字母,Java中有专门的方法

即:Character.isDigit()和Character.isLetter()

4.下列程序运行结果:

public class Example{
    String str = new String("good");
    char[ ] ch = { 'a' , 'b' , 'c' };
    public static void main(String args[]){
        Example ex = new Example();
        ex.change(ex.str,ex.ch);
        System.out.print(ex.str + " and ");
        System.out.print(ex.ch);
    }
    public void change(String str,char ch[ ]){
        str = "test ok";
        ch[0] = 'g';
    }
}

good and gbc

主要考察传引用会发生的问题。分为两种情况

  1. 通过引用,修改原来的内存
  2. 通过引用,修改当前引用的指向

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值