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

news2024/11/19 1:24:31

[本节目标]

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。
 

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

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

相关文章

差异计算基础知识 - 了解期末业务操作、WIP 和差异

原文地址&#xff1a;Basics of variance calculation-Understanding Period End activities, WIP and Variances | SAP Blogs 大家好&#xff0c; 这是我在成本核算方面的第六份文件&#xff0c;旨在解释期末的差异计算和相关活动。 我将引导您完成期末活动和差异计算。在本文…

Spring Cloud Gateway 网关的基础使用

1. 什么是网关&#xff1f;网关有什么用&#xff1f; 在微服务架构中&#xff0c;网关就是一个提供统一访问地址的组件&#xff0c;它解决了内部微服务与外部的交互问题。网关主要负责流量的路由和转发&#xff0c;将外部请求引到对应的微服务实例上。同时提供身份认证、授权、…

前后端数据传输格式(下)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 上篇主要复习了HTTP以及…

解释AI决策,这10个强大的 Python 库记得收藏!

本文整理了10个常用于可解释AI的Python库&#xff0c;方便我们更好的理解AI模型的决策。 什么是XAI&#xff1f; XAI&#xff08;Explainable AI&#xff09;的目标是为模型的行为和决策提供合理的解释&#xff0c;这有助于增加信任、提供问责制和模型决策的透明度。XAI 不仅…

鸿蒙生态开发就业前景到底好不好

鸿蒙生态开发是指基于华为自主研发的操作系统鸿蒙&#xff08;HarmonyOS&#xff09;进行应用程序开发和生态建设。目前&#xff0c;鸿蒙生态开发的前景非常好&#xff0c;原因如下&#xff1a;做鸿蒙应用开发到底学习些啥&#xff1f; (qq.com) 1&#xff1a;政府支持&#x…

高德地图vue实现自定义标点热力图效果(缩放时展示不同数据)

高德地图插件引入省略。。。样式和vue基础组件省略。。。 如果每个标点没有数值&#xff0c;则可以用点聚合来实现功能下面例子&#xff0c;每个标点会有按市统计的数值&#xff0c;而且缩放一定程度时&#xff0c;需要展示按省统计的标点&#xff0c;因此需要自定义标点样式和…

Ubuntu中编译出Windows的可执行程序(.exe)

1、前言 在嵌入式开发中&#xff0c;交叉编译是很常见的情况&#xff0c;如果你把Windows电脑也看做一块高性能的开发板&#xff0c;那在Ubuntu中编译出Windows上运行的可执行程序也是很好理解的行为。 2、安装mingw64环境 sudo apt-get install mingw-w64 3、测试编译链是否安…

特权FPGA 学习笔记

存储器可用于异步时钟域的信号处理&#xff0c;双口RAM多用于交互式数据&#xff0c;FIFO多用于单向数据传输&#xff1b;以task的方式封装testbench子程序&#xff0c;以提高复用程度&#xff1b;模板中&#xff0c;vho是vhdl模板&#xff0c;veo是verilog模板&#xff1b;run…

第七届中老越三国丢包狂欢节暨2023年中老越三国(普洱)边境商品交易会新闻发布会在昆明召开

12月8日&#xff0c;第七届中老越三国丢包狂欢节暨2023年中老越三国&#xff08;普洱&#xff09;边境商品交易会新闻发布会在昆明召开。据悉&#xff0c;本届丢包节暨边交会将于2023年12月22日至26日在普洱市江城哈尼族彝族自治县举办。 发布会现场 中老越三国丢包狂欢节自200…

解决 php 连接mysql数据库时报错:Fatal error: Class ‘mysqli’ not found in问题

在使用php对mysql进行连接的过程中&#xff0c;出现了Fatal error: Uncaught Error: Class "mysqli" not found in的问题 解决方案 这个错误通常表示您的PHP代码中缺少MySQL扩展或者没有启用MySQL扩展。 我们首先确认一下PHP环境中已经安装了MySQL扩展。检查一下自己…

v4l2接收流程

内核media驱动目录结构 目录media/driver,子目录说明如下&#xff0c;主要列举本文中使用到的目录 目录功能I2C摄像头&#xff0c;解串器&#xff08;max9296/9295等&#xff09;platform控制器的驱动&#xff0c;例如mipi控制等v4l2_coreioctl 入口等media\common\videobuf2…

哈希表的几种实现方式与比较

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 哈希表概述 哈希表&#xff08;Hash Table&#xff09;是一种常用的数据结构&#xff0c;用于实现键值对的映射关系。它通过哈希函数将键映射到一个特定的索引位置&#xf…

Spring Boot 3 整合 Mybatis-Plus 实现动态数据源切换实战

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

银河麒麟本地软件源配置方法

软件源介绍 软件源可以理解为软件仓库&#xff0c;当需要安装软件时则会根据源配置去相应的软件源下载软件包&#xff0c;此方法的优点是可以自动解决软件包的依赖关系。常见的软件源有光盘源、硬盘源、FTP源、HTTP源&#xff0c;本文档主要介绍本地软件源的配置方法&#xff…

专注抖音短视频账号矩阵系统源头开发---saas工具

抖音账号|短视频矩阵分发系统 | 多账号管理发布 |MVC架 短视频矩阵分发系统是一种可以帮助企业、机构和个人高效分发短视频的工具。随着社交媒体的不断普及&#xff0c;短视频的使用越来越广泛&#xff0c;因此如何快速而准确地将短视频传播到不同的平台和账号上已经成为了一个…

短剧分销平台搭建:短剧变现新模式

短剧作为今年大热的行业&#xff0c;深受大众追捧&#xff01;短剧剧情紧凑&#xff0c;几乎每一集都有高潮剧情&#xff0c;精准击中了当下网友的碎片化时间。 短剧的形式较为灵活&#xff0c;可以轻松融入各种的元素&#xff0c;比如喜剧、悬疑、爱情等&#xff0c;可以满足…

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

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

postman常用脚本

一、在参数中动态添加开始时间和结束时间的时间戳 1.先在collection中添加参数&#xff0c;这里的作用域是collection&#xff0c;也可以是其他的任何scope 2.在Pre-request Script 中设定开始时间和结束时间参数&#xff0c;比如昨天和今天的时间戳&#xff0c;下面是js代码 …

彻底搞懂零拷贝技术( DMA、PageCache)

DMA 直接内存访问&#xff08;Direct Memory Access&#xff09; 什么是DMA&#xff1f; 在进行数据传输的时候&#xff0c;数据搬运的工作全部交给 DMA 控制器&#xff0c;而 CPU 不再参与&#xff0c;可以去干别的事情。 传统I/O 在没有 DMA 技术前&#xff0c;全程数据…

【图论笔记】克鲁斯卡尔算法(Kruskal)求最小生成树

【图论笔记】克鲁斯卡尔算法&#xff08;Kruskal&#xff09;求最小生成树 适用于 克鲁斯卡尔适合用来求边比较稀疏的图的最小生成树 简记&#xff1a; 将边按照升序排序&#xff0c;选取n-1条边&#xff0c;连通n个顶点。 添加一条边的时候&#xff0c;如何判断能不能添加…