Java(十一)---String类型

文章目录


前言

上一篇我们学习了创建一个图书管理系统,更加深入地复习类和对象、面向对象,继承,多态以及接口 等相关内容,今天我们学习一个新的内容---String类型


1.String类的重要性

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


2.常用方法

2.1.字符串的创建

主要有三种:

1.String 变量名="内容";(注意是双引号)

2.String 变量名=new String("内容");

3.利用字符数组,创建字符串

java 复制代码
public static void main(String[] args) {
        String str1="hello";
        String str2=new String(" world");
        char[]chars={'a','b','c','d'};
        String str3=new String(chars);
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
    }

2.2.字符串的比较

字符串的比较主要有4种方法(==,equals,compareTo,compareToIgnoreCase)

2.2.1.==比较是否引用同一个对象

java 复制代码
public static void main(String[] args) {
        String str1=new String("hello");
        String str2=new String("hello");
        String str3=str1;
        System.out.println(str1==str2);
        System.out.println(str1==str3);
        System.out.println(str2==str3);
    }

为什么?

我们画个图来解释一下

由此可知,==是比较两个String类型的地址,那么如果我们只想比较两个String类型中值是否一样,那么就要使用equals方法

2.2.2.boolean equals(Object anObject) 方法:

按照字典序比较字典序:字符大小的顺序

String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照如下规则进行比较,比如: s1.equals(s2)

java 复制代码
 public static void main(String[] args) {
        String str1=new String("hello");
        String str2=new String("hello");
        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));
        System.out.println(str2.equals(str3));
    }

2.2.3.int CompareTo(String s)

如果我们要比较两个字符串的大小,那么就不能使用equals方法,而要使用compareTo方法。

java 复制代码
 public static void main(String[] args) {
        String s="abcd";
        String s1="agada";
        int ret=s.compareTo(s1);
        System.out.println(ret);
    }

2.2.4.int compareToIgnoreCase(String str) 方法:

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

java 复制代码
public static void main(String[] args) {
        String s2="Admin";
        String s3="admin";
        int ret1=s2.compareToIgnoreCase(s3);
        System.out.println(ret1);
    }

2.3.字符串的查找

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

有这么多的方法,具体大家自己去实践,在这只提供参考代码:

java 复制代码
public static void main(String[] args) {
        String s="aabcabcddcba";
        //chatAt(i)返回i下标的字符
        for (int i=0;i<s.length();i++){
            System.out.print(s.charAt(i)+" ");
        }
        //indexof()
        int ret=s.indexOf('b');
        int ret1=s.indexOf("bc");
        int ret2=s.indexOf("b",4);
        int ret3=s.indexOf("dd",3);
        //lastIndexOf()从后往前找
        int ret4=s.lastIndexOf("d");
        int ret5=s.lastIndexOf('b');
        int ret6=s.lastIndexOf("cd",3);
        int ret7=s.lastIndexOf('c',4);
        System.out.println("======");
        System.out.print(ret+" ");
        System.out.print(ret1+" ");
        System.out.print(ret2+" ");
        System.out.print(ret3+" ");
        System.out.print(ret4+" ");
        System.out.print(ret5+" ");
        System.out.print(ret6+" ");
        System.out.print(ret7+" ");
    }

2.4.字符串的转化

2.4.1.数值和字符串之间转化

数值转化为字符串

java 复制代码
public static void main(String[] args) {
        int a=10;
        double b=20.6;
        boolean flg=true;
        String s1=String.valueOf(a);
        String s2=String.valueOf(b);
        String s3=String.valueOf(flg);
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
    }

字符串转化为数值

java 复制代码
public static void main(String[] args) {
        String s1="10";
        String s2="20.4";
        String s3="false";
        int a=Integer.valueOf(s1);
        double b= Double.valueOf(s2);
        boolean c=Boolean.valueOf(s3);
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }

2.4.2.大小写转化

toLowerCase();大写转化为小写

toUpperCase();小写转化为大写

java 复制代码
    public static void main(String[] args) {
        String s1="HEllo";
        s1=s1.toLowerCase();
        System.out.println(s1);
        System.out.println("=========");` String s1=String.format("%d-%d-%d",2000,1,1);
        System.out.println(s1);
        String s2="hEllO";
        s2=s2.toUpperCase();
        System.out.println(s2);
    }

2.4.3.字符串转化为字符数组

java 复制代码
public static void main(String[] args) {
        String s="Hello world";
        char[]chars=s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            System.out.print(chars[i]+" ");
        }
    }

2.4.4.格式化

java 复制代码
		String s1=String.format("%d-%d-%d",2000,1,1);
        System.out.println(s1);

2.5.字符串的替换

String replaceAll(String regex, String replacement) 替换所有内容

String replaceFirst(String regex, String replacement) 替换首个内容

java 复制代码
public static void main(String[] args) {
        String s1="ababcabdeaf";
        String ret1=s1.replaceFirst("a","b");
        System.out.println(ret1);
        System.out.println("======");
        String ret2=s1.replace('a','o');
        System.out.println(ret2);

    }

2.6 字符串拆分

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

可用方法如下:

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

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

java 复制代码
 public static void main(String[] args) {
        String s1="hello world";
        String[]strings=s1.split(" ");
        for (String s:strings){
            System.out.println(s);
        }
    }
java 复制代码
public static void main(String[] args) {
        String s1="hello world hello world";
        String[]strings=s1.split(" ",2);
        for(String s:strings){
            System.out.println(s);
        }
    }

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义.

代码示例: 拆分IP地址

java 复制代码
 public static void main(String[] args) {
        String str = "192.168.1.1" ;
        String[] result = str.split("\\.") ;
        for(String s: result) {
            System.out.println(s);
        }
    }

注意事项:

  1. 字符"|","*","+"都得加上转义字符,前面加上 "\" .
  2. 而如果是 "" ,那么就得写成 "\\" .
  3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.
    代码示例: 多次拆分
java 复制代码
 public static void main(String[] args) {
        String s="name=zhangsan&age=18";
        String[]strings=s.split("&");
        for(int i=0;i<strings.length;i++){
            String[]strings1=strings[i].split("=");
            for (int j=0;j< strings1.length;j++){
                System.out.print(strings1[j]+" ");
            }
            System.out.println();
        }
    }

这样写比较麻烦,还有一种方式

java 复制代码
 public static void main(String[] args) {
        String s="name=zhangsan&age=18";
        String[]strings=s.split("&|=");
        for (int i=0;i< strings.length;i++){
            System.out.println(strings[i]);
        }
    }

2.7 字符串截取

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

String substring(int beginIndex) 从指定索引截取到结尾

String substring(int beginIndex, int endIndex) 截取部分内容

java 复制代码
 public static void main(String[] args) {
        String s="abcabcde";
        String s1=s.substring(0,3);
        String s2=s.substring(3);
        System.out.println(s1);
        System.out.println("====");
        System.out.println(s2);
    }

注意事项:

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

2.8.其他操作方法

String trim() 去掉字符串中的左右空格,保留中间空格

java 复制代码
public static void main(String[] args) {
        String s="   hel l o w  orld   ";
        System.out.println(s);
        String s1=s.trim();
        System.out.println(s1);
    }

2.9.字符串的不变性

大家会发现,许多方法我们在使用完的时候,我们要用一个字符串进行接受。这是因为String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:

1 . String类在设计时就是不可改变的,String类实现描述中已经说明了

String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:

  1. String类被final修饰,表明该类不能被继承
  2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中
    的内容可以修改。

2 . 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象.

以replace为例

final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。

c 复制代码
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};
    }

会报错

已经初始化完了array数组,可以改变其中某个具体的值,但是就不能在进行初始化。

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

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

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

java 复制代码
public static void main(String[] args) {
        String s="hello";
        s+=" world";
        System.out.println(s);
    }

其反汇编代码

其实等价于

java 复制代码
public static void main(String[] args) {
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("hello");
        stringBuilder.append(" world");
        String s=stringBuilder.toString();
        System.out.println(s);
    }

通过下面的代码观察+法,和append方法的效率

java 复制代码
 public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String s = "";
        for(int i = 0; i < 10000; ++i){
            s += i;
        } 
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");
        for(int i = 0; i < 10000; ++i){
            sbf.append(i);
        } 
        end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuilder sbd = new StringBuilder();
        for(int i = 0; i < 10000; ++i){
            sbd.append(i);
        } 
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }

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


3. StringBuilder和StringBuffer

3.1 StringBuilder的介绍

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

部分功能是相同的,这里介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅StringBuilder在线文档

这么多方法,大家以后要是有不会的,在进行使用吧。

java 复制代码
 public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder("hello");
        StringBuilder sb2 = sb1;
		// 追加:即尾插-->字符、字符串、整形数字
        sb1.append(' '); // hello
        sb1.append("world"); // hello world
        sb1.append(123); // hello world123
        System.out.println(sb1); // hello world123
        System.out.println(sb1 == sb2); // true
        System.out.println(sb1.charAt(0)); // 获取0号位上的字符 h
        System.out.println(sb1.length()); // 获取字符串的有效长度14
        System.out.println(sb1.capacity()); // 获取底层数组的总大小
        sb1.setCharAt(0, 'H'); // 设置任意位置的字符 Hello world123
        sb1.insert(0, "Hello world!!!"); // Hello world!!!Hello world123
        System.out.println(sb1);
        System.out.println(sb1.indexOf("Hello")); // 获取Hello第一次出现的位置
        System.out.println(sb1.lastIndexOf("hello")); // 获取hello最后一次出现的位置
        sb1.deleteCharAt(0); // 删除首字符
        sb1.delete(0,5); // 删除[0, 5)范围内的字符
        String str = sb1.substring(0, 5); // 截取[0, 5)区间中的字符以String的方式返回
        System.out.println(str);
        sb1.reverse(); // 字符串逆转
        str = sb1.toString(); // 将StringBuffer以String的方式返回
        System.out.println(str);
    }

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

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

String变为StringBuilder: 利用StringBuilder的构造方法或append()方法

StringBuilder变为String: 调用toString()方法。

3.2 面试题:

String、StringBuffer、StringBuilder的区别

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

StringBuffer与StringBuilder大部分功能是相似的

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作。


4.String OJ题

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

  1. 最后一个单词的长度

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


相关推荐
bug菌21 分钟前
Java GUI编程进阶:多线程与并发处理的实战指南
java·后端·java ee
Манго нектар25 分钟前
JavaScript for循环语句
开发语言·前端·javascript
程序猿小D34 分钟前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
阿华的代码王国42 分钟前
【JavaEE】——文件IO的应用
开发语言·python
satan–01 小时前
R语言的下载、安装及环境配置(Rstudio&VSCode)
开发语言·windows·vscode·r语言
电饭叔1 小时前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student1 小时前
everyday_question dq20240731
开发语言·arm开发·php
极客先躯1 小时前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略
卑微求AC2 小时前
(C语言贪吃蛇)11.贪吃蛇方向移动和刷新界面一起实现面临的问题
c语言·开发语言
夜月行者2 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm