对String类的操作 (超细节+演示)

[本节目标]

1.认识String类

2.了解String类的基本用法

3.熟练掌握String类的常见操作

4.认识字符串常量池

5.认识StringBuffer和StringBuilder

1.String类的重要性

在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提
供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字
符串应用又非常广泛,因此Java语言专门提供了String类。
在开发和校招笔试中,字符串也是常客,比如:
字符串转整形数字
字符串相加
而且在面试中也频繁被问到,比如:String、StringBuff和StringBulider之间的区别等。

2.常用方法

2.1. 字符串构造

String类提供的构造方式非常多,常用的就以下三种:

public class Test8 {
    public static void main(String[] args) {


        //使用常量串构造
        String s1 = "hello shousidaima";
        System.out.println(s1);

        //直接newString对象
        String s2 = new String("hello shousidaima");
        System.out.println(s2);

        //使用字符数组进行构造
        char[] arr = {'h','e','l','l','o'};
        String s3 = new String(arr);
        System.out.println(s3);
    }
}

[注意]

1. String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:

// 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类型对象.

 System.out.println("hello".length());   //打印长度

2.2 String对象的比较

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

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

对象:对于内置类型, ==比较的是变量中的值:对于引用类型==比较的是引用地址.

int a = 10;
int b = 20;
int c = 10;
// 对于基本类型变量,==比较两个变量中存储的值是否相同
System.out.println(a == b); // false
System.out.println(a == c); // true
// 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("world");
String s4 = s1;
System.out.println(s1 == s2);// false
System.out.println(s2 == s3); // false
System.out.println(s1 == s4); // true

2.boolean equals(Object anObject) 方法:按照字典序比较

字典序:字符大小的顺序

String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals后,按照如下规则比较,比如:s1.equals(s2)   注意!这是java重写的,不是让我们自己重写

@Override
       public boolean equals(Object anObject) {
// 1. 先检测this 和 anObject 是否为同一个对象比较,如果是返回true
if (this == anObject) {
return true;
}

// 2. 检测anObject是否为String类型的对象,如果是继续比较,否则返回false
if (anObject instanceof String) {
// 将anObject向下转型为String类型对象
String anotherString = (String)anObject;
int n = value.length;

// 3. this和anObject两个字符串的长度是否相同,是继续比较,否则返回false
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;

// 4. 按照字典序,从前往后逐个字符进行比较
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
      

       }
      }

3.int compartTo(String s)方法:按照字典序进行比较

与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:

1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值

String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("abc");
String s4 = new String("abcdef");
System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
System.out.println(s1.compareTo(s3)); // 相同输出 0
System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3

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

String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("ABc");
String s4 = new String("abcdef");
System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3

2.3 字符串查找

字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法:
1.char charAt(int index)
返回index位置上字符,如果index为负数或者越界,抛出
IndexOutOfBoundsException异常


2.int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
3.int indexOf(int ch, int fromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有返回-1


4.int indexOf(String str) 返回str第一次出现的位置,没有返回-1


5.int indexOf(String str, intfromIndex)从fromIndex位置开始找str第一次出现的位置,没有返回-1


6.int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1


7.int lastIndexOf(int ch, int fromIndex)从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1


8. int lastIndexOf(String str) 从后往前找,返回str第一次出现的位置,没有返回-1


9.int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返

注意:上述方法都是实例方法。

2.4 转化

1.数值和字符串转化

   // 数字转字符串
String s1 = String.valueOf(1234);
String s2 = String.valueOf(12.34);
String s3 = String.valueOf(true);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);

// 字符串转数字
// 注意:Integer、Double等是Java中的包装类型,这个后面会讲到
int data1 = Integer.parseInt("1234");
double data2 = Double.parseDouble("12.34");
System.out.println(data1);
System.out.println(data2);

2.大小写转换

String s1 = "hello";
String s2 = "HELLO";

3.字符串转数组

  //字符串转数组
String s1 = "acbd";
char[] arr = s1.toCharArray();
       for (int i = 0; i < arr.length ;i++) {
           System.out.println(arr[i]);
       }
       //数组转字符串
       String s2 = new String(arr);
       System.out.println(s2);

4.格式化

 String s = String.format("%d-%d-%d", 2019, 9,14);
System.out.println(s);

2.5 字符串替换

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

String str = "helloworld" ;
       System.out.println(str.replaceAll("l", "_"));
       System.out.println(str.replaceFirst("l", "_"));

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

2.6 字符串拆分

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

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

代码示例:实现字符串的拆分处理(全部)

 String str = "hello world hello bit" ;
       String[] result = str.split("l") ; // 按照空格拆分
       for(String s: result) {
System.out.print(s);
       }

代码示例:字符串的部分拆分

String str = "hello world hello bit" ;
       String[] result = str.split("ll",2) ;
       for(String s: result) {
System.out.println(s);

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

代码示例:拆分IP地址

String str = "192.168.1.1" ;
       String[] result = str.split("\\.") ;
       for(String s: result) {
System.out.println(s);

注意事项:

1. 字符"|", "*","+"都得加上转义字符,前面加上\\

2.而如果是"\",那么就得写成"\\\\"

3.如果一个字符串中有多个分隔符,可以用"|"作为连字符

代码示例:多次拆分

 String str = "name=zhangsan&age=18" ;
       String[] result = str.split("&") ;
       for (int i = 0; i < result.length; i++) {
String[] temp = result[i].split("=") ;
System.out.println(temp[0]+" = "+temp[1]);
       }
       }

2.7 字符串截取

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

方法                                                                    功能
String substring(int beginIndex)                       从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容

 String str = "helloworld" ;
       System.out.println(str.substring(5));
       System.out.println(str.substring(0, 5));

注意事项:

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

2.8 其他操作方法

代码示例:观察trim()方法使用

 String str = " hello world " ;
       System.out.println("["+str+"]");
       System.out.println("["+str.trim()+"]");

代码示例:大小写转换

  String str = " hello%$$%@#$%world 哈哈哈 " ;
       System.out.println(str.toUpperCase());
       System.out.println(str.toLowerCase());

这两个函数只转换字母

2.9  字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:
1. String类在设计时就是不可改变的,String类实现描述中已经说明了
以下来自JDK1.8中String类的部分实现:


1. String类被final修饰,表明该类不能被继承
2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中
的内容可以修改。
2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象

【纠正】网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。
这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。
final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的

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

那如果想要修改字符串中内容,该如何操作呢?

3.StringBuilder和StringBuffer

3.1 StringBuilder的介绍

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的,这里介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅 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的方式返回

示例:

import java.util.Arrays;

public class Test12 {
    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()方法。

String、StringBuffer、StringBuilder的区别

相同点:底层都是通过char数组实现的
不同点:

String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;
StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

redis主从复制【面试必看】

在分布式系统中&#xff0c;希望使用多个服务器来部署redis&#xff0c;存在以下几种redis的部署方式 主从模式主从哨兵集群模式 主从模式 在若干个redis节点中&#xff0c;有的是主节点&#xff0c;有的是从节点 假设有三个物理服务器&#xff08;称为是三个节点&#xff…

1-4、JDK目录结构

语雀原文链接 文章目录 1、目录结构2、JDK中rt.jar、tools.jar和dt.jar作用3、bin目录部分说明&#xff08;基本工具&#xff09; 1、目录结构 bin目录&#xff1a;包含一些用于开发Java程序的工具&#xff0c;例如&#xff1a;编译工具(javac.exe)、运行工具 (java.exe) 、打…

【论文阅读笔记】序列数据的数据增强方法综述

【论文阅读笔记】序列数据的数据增强方法综述 摘要 这篇论文探讨了在深度学习模型中由于对精度的要求不断提高导致模型框架结构变得更加复杂和深层的趋势。随着模型参数量的增加&#xff0c;训练模型需要更多的数据&#xff0c;但人工标注数据的成本高昂&#xff0c;且由于客观…

kettle完成mysql表与表之间的更新和插入

版本&#xff1a;20231209 kettle完成数据库表与表之间的转换非常的简单&#xff0c;只需要在输入模块选择&#xff1a;输入表&#xff1b;在输出模块选择&#xff1a;插入和更新表模块 实例展示&#xff1a;将表stu1的数据同步到stu2&#xff0c;并覆盖掉stu2原本的数据。 cr…

Ubuntu 18.04使用Qemu和GDB搭建运行内核的环境

安装busybox 参考博客&#xff1a; 使用GDBQEMU调试Linux内核环境搭建 一文教你如何使用GDBQemu调试Linux内核 ubuntu22.04搭建qemu环境测试内核 交叉编译busybox 编译busybox出现Library m is needed, can’t exclude it (yet)的解释 S3C2440 制作最新busybox文件系统 https:…

【Com通信】Com模块详细介绍

目录 前言 1. Com模块功能介绍 2.关键概念理解 3.功能详细设计 3.1 Introduction 3.2 General Functionality 3.2.1 AUTOSAR COM basis 3.2.2 Signal Values 3.2.3 Endianness Conversion and Sign Extension 3.2.4 Filtering 3.2.5 Signal Gateway 3.3 Normal Ope…

Bean的作用域和生命周期

1. Bean的作用域 前引例子4 现在有一个公共的Bean对象&#xff0c;提供给A用户和B用户使用&#xff0c;然而在使用的时候A用户将Bean对象的数据进行修改&#xff0c;此时B得到的Bean对象是否是原来的Bean对象呢&#xff1f; Componentpublic class Users {Beanpublic User us…

人工智能原理复习--搜索策略(二)

文章目录 上一篇启发式搜索与或图搜索博弈下一篇 上一篇 人工智能原理复习–搜索策略&#xff08;一&#xff09; 启发式搜索 提高一般图搜索效率的关键是优化OPEN表中节点的排序方式 最理想的情况是每次排序OPEN表表首n总在解答路径上 全局排序–对OPEN表中的所有节点进行…

馆藏档案管理系统和数字档案管理系统的区别

馆藏档案管理系统是指传统的档案管理系统&#xff0c;主要包括档案馆内纸质档案的收集、整理、存储、保护、利用等工作。它的主要特点是针对纸质档案的管理&#xff0c;需要建立大量的文件柜、卷宗和保管设备&#xff0c;检索和借阅需要现场操作。 专久智能数字档案管理系统则是…

文献速递:多模态影像组学文献分享:多模态图注意力网络用于COVID-19预后预测

文献速递&#xff1a;多模态影像组学文献分享&#xff1a;多模态图注意力网络用于COVID-19预后预测 01 文献速递介绍 在处理像 COVID-19 这样的新出现的疾病时&#xff0c;患者和疾病特定因素&#xff08;例如&#xff0c;体重或已知共病&#xff09;对疾病的即时进展的影响…

使用智能AI文心一言处理采集数据

简数采集器支持调用百度智能AI文心一言大模型API接口&#xff0c;可对采集的数据进行研究分析&#xff0c;内容创作。 文心一言API使用方法如下&#xff1a; 目录 1. 采集数据 2. 申请API 3. 对接文心一言API 4. 设置文心一言API的执行指令 5. 使用文心一言API处理采集数…

案例061:基于微信小程序的互助学习系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

54.grpc实现文件上传和下载

文章目录 一&#xff1a;简介1. 什么是grpc2. 为什么我们要用grpc 二&#xff1a;grpc的hello world1、 定义hello.proto文件2、生成xxx_grpc.pb.go文件3、生成xxx.pb.go结构体文件4、编写服务代码service.go5、编写客户端代码client.go 三、服务端流式传输&#xff1a;文件下载…

pycharm安装

1.先去官网下载pycharm 2.下载python3.8 3.修改pip镜像 4.如果有环境变量没加的加一下

一加 12 Pop-up快闪活动来袭,十城联动火爆开启

12 月 9 日&#xff0c;一加 12 Pop-up 快闪活动在北京、深圳、上海、广州等十城联动开启&#xff0c;各地加油欢聚快闪现场&#xff0c;抢先体验与购买一加 12。作为一加十年超越之作&#xff0c;一加 12 全球首发拥有医疗级护眼方案和行业第一 4500nit 峰值亮度的 2K 东方屏、…

我尝试用 AI 来做数据分析,结果差强人意!

大家好&#xff0c;我是木川 工作中经常会需要分析数据 1、统计分析&#xff0c;计算某项指标的均值、分位数、标准差等 2、相关性分析&#xff0c;比如分析销售额与顾客年龄、顾客性别、促销活动等的相关性 3、可视化分析&#xff0c;比如绘制柱状图、折线图、散点图等 有了 A…

Java网络编程——对象的序列化与反序列化

当两个进程进行远程通信时&#xff0c;彼此可以发送各种类型的数据&#xff0c;如文本、图片、语音和视频等。无论是何种类型的数据&#xff0c;都会以二进制序列的形式在网络上传送。当两个Java进程进行远程通信时&#xff0c;一个进程能否把一个Java对象发送给另一个进程呢&a…

本地部署语音转文字(whisper,SpeechRecognition)

本地部署语音转文字 1.whisper1.首先安装Chocolatey2.安装3.使用 2.SpeechRecognition1.环境2.中文包3.格式转化4.运行 3.效果 1.whisper 1.首先安装Chocolatey https://github.com/openai/whisper 以管理员身份运行PowerShell Set-ExecutionPolicy Bypass -Scope Process -…

自动化测试框架性能测试报告模板

一、项目概述 1.1 编写目的 本次测试报告&#xff0c;为自动化测试框架性能测试总结报告。目的在于总结我们课程所压测的目标系统的性能点、优化历史和可优化方向。 1.2 项目背景 我们公开课的性能测试目标系统。主要是用于我们课程自动化测试框架功能的实现&#xff0c;以及…

记录 | ubuntu监控cpu频率、温度等

ubuntu监控cpu频率、温度等 采用 i7z 进行监控&#xff0c;先安装&#xff1a; sudo apt install i7z -ysudo i7z