Java:String类

目录

  • 1.String类的重要性
  • 2.String对象的比较
    • 2.1 ==比较是否引用同一个对象
    • 2.2 `boolean equals(Object anObject)` 方法:按照字典序比较
    • 2.3`int compareTo(String s)`方法: 按照字典序进行比较
    • 2.4 `boolean equalsIgnoreCase(Object anObject)`方法:忽略大小写的比较方法
  • 3. 字符串查找
  • 4.转换
    • 4.1 数值和字符串转化
    • 4.2 大小写转换
    • 4.3 字符串转数组
    • 4.4 格式化
  • 5. 字符串替换
  • 6. 字符串拆分
  • 7. 字符串截取
  • 8. `trim()`方法
  • 9.字符串的不可变性
  • 10. 字符串修改
  • 11. `StringBuilder类`和`StringBuffer类`

1.String类的重要性

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

public class Test {public static void main(String[] args) {//直接赋值法String str="abcdef";//实例化对象法String str2=new String("hello");//字符数组转换法char[] array={'a','b','c','d'};String str3=new String(array);System.out.println(str);System.out.println(str2);System.out.println(str3);}
}

上面只是常见的三种方法,其他方法需要用到时,大家参考Java在线文档:String官方文档

2.String对象的比较

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

我们先来看下面这段代码

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

运行上面的代码,我们可以看到输出结果:(str1str2)输出true;(str3str4)输出false。
那么我们要怎么来理解上面的这个输出结果呢?
首先我们知道Java中规定:只要是双引号引起来的字符常量,会存在一个字符常量池当中。
储存逻辑
1.先检查这个内存(字符串常量池)有没有这个字符串
2.如果没有,存一个新的进去
3.如果有,就不重复储存了。取出现有的对象即可。
通过上面的知识点,我们得知“str1和str2”指向同一对象,而“==”就是看是否指向同一对象,所以前者输出true;而str4通过new创建了一个新的对象,str3和str4并不是指向同一对象,所以输出false。

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

String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照如下规则进行比较。举例如下:

        String str3="abcdef";String str4=new String("abcdef");System.out.println(str3.equals(str4));

运行上方代码我们可以看到输出结果和2.1中不一样,输出的是true。equals就是对字符串的内容进行比较,当两个字符串一样时输出true,否则输出false。

2.3int compareTo(String s)方法: 按照字典序进行比较

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

public class Main {public static void main(String[] args) {String str3="abcdef";String str4=new String("abcdef");System.out.println(str3.compareTo(str4));//输出0,两个字符串一样String str5="abcdef";String str6="abcdefgh";System.out.println(str5.compareTo(str6));//输出-2,前面字符串相同str6比str5长2,str5长度减str6长度String str7="abcdef";String str8="ad";System.out.println(str7.compareTo(str8));//输出-2,b的ASCII码值减d的ASCII码值为-2}
}

输出结果和结果解释看代码注释。

2.4 boolean equalsIgnoreCase(Object anObject)方法:忽略大小写的比较方法

代码如下

   public static void main(String[] args) {String str1="Abcd";String str2="abcd";System.out.println(str1.equals(str2));System.out.println(str1.equalsIgnoreCase(str2));}

输出结果为false和true。
使用场景:验证码验证信息。

3. 字符串查找

字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法:
在这里插入图片描述
下面我们来一个一个用代码展示
1.char charAt(int index)方法

public static void main(String[] args) {String str1="abcde";System.out.println(str1.charAt(0));}

输出结果:a
返回index(下标)位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常

2.int indexOf(int ch)方法

public static void main(String[] args) {String str1="abcd";int p=str1.indexOf("d");System.out.println(p);}

输出:3
找到要寻找的字符第一次出现的下标,如没有返回-1。

3.int indexOf(int ch, int fromIndex)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.indexOf("d",4);System.out.println(p);}

输出结果:7
从指定位置之后开始寻找(包含这个位置),找到要寻找的字符第一次出现的下标,如没有返回-1。

4.int indexOf(String str)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.indexOf("bc");System.out.println(p);}

输出结果:1
找指定字符串第一次出现的位置并返回首元素的地址,如果没找到对应字符串返回-1

5.int indexOf(String str, int fromIndex)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.indexOf("bc",4);System.out.println(p);}

输出结果:5
从指定位置之后开始寻找(包含这个位置),找指定字符串第一次出现的位置并返回首元素的地址,如果没找到对应字符串返回-1

6.int lastIndexOf(int ch)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.lastIndexOf("a");System.out.println(p);}

输出结果:4
从字符串的后面往前找,返回要找字符第一次出现的下标,如果没找到返回-1。

7.int lastIndexOf(int ch, int fromIndex)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.lastIndexOf("a",3);System.out.println(p);}

输出结果:0
从指定位置(包含这个位置)往前找,返回要找字符第一次出现的下标,如果没找到返回-1。

8.int lastIndexOf(String str)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.lastIndexOf("bc");System.out.println(p);}

输出结果:5
从字符串的后面往前找,找到指定字符串第一次出现的位置并返回首元素的地址,如果没找到对应字符串返回-1。

9.int lastIndexOf(String str, int fromIndex)方法

public static void main(String[] args) {String str1="abcdabcd";int p=str1.lastIndexOf("bc",4);System.out.println(p);}

输出结果:1
从指定位置(包含这个位置)往前找,找到指定字符串第一次出现的位置并返回首元素的地址,如果没找到对应字符串返回-1。

4.转换

4.1 数值和字符串转化

public static void main(String[] args) {// 数字转字符串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);System.out.println("=================================");// 字符串转数字int data1 = Integer.parseInt("1234");double data2 = Double.parseDouble("12.34");System.out.println(data1);System.out.println(data2);}

输出结果
在这里插入图片描述
上面的valueOfparseIntparseDouble都是直接通过类名进行调用,通过追溯原码可以发现这些都是被static修饰的静态方法,可直接用类名进行调用。

4.2 大小写转换

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

输出结果:
在这里插入图片描述
toLowerCase()方法将大写转化为小写,toUpperCase()方法将小写转化成大写。

4.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);}

运行结果
在这里插入图片描述

toCharArray()方法可以将字符串转化为字符数组,通过new String(char[])可以将一个字符数组转化成字符串的形式

4.4 格式化

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

运行结果
在这里插入图片描述
format()方法可将字符格式化成想要的格式,并存入字符串中。通过类名直接调用。

5. 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:
在这里插入图片描述
举例如下

public static void main(String[] args) {String str1="hello world";System.out.println(str1.replace('l','_'));System.out.println(str1.replaceAll("l","__"));System.out.println(str1.replaceFirst("l","__"));}

运行结果
在这里插入图片描述

6. 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
可用方法如下:
在这里插入图片描述

public static void main(String[] args) {String str="hello world hello zzuli";String[] str2=str.split(" ");//按照空格拆分for(String s:str2) {System.out.println(s);}System.out.println("==============");String[] str3=str.split(" ",3);//按照空格拆分成3组,从左往右for(String s:str3){System.out.println(s);}}

运行结果
在这里插入图片描述
拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义。
注意事项

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

举例:
IP地址的拆分

public static void main(String[] args) {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 str = "name=zhangsan&age=18" ;String[] str1=str.split("&");for(String s:str1){System.out.println(s);}System.out.println("============");for(String s:str1){String[] str2=s.split("=");System.out.println(str2[0]+":"+str2[1]);}}

运行结果
在这里插入图片描述

7. 字符串截取

从一个完整的字符串之中截取出部分内容。可用方法如下:
在这里插入图片描述

public static void main(String[] args) {String str="hello zzuli";System.out.println(str.substring(4));//打印字符串下标为4往后的字符串System.out.println(str.substring(6,11));//打印下标从6到11的字符串}

运行结果
在这里插入图片描述
注意事项:

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

8. trim()方法

trim()能去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等).举例如下

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

运行结果
在这里插入图片描述

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}

但是这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。
在这里插入图片描述

 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。

11. StringBuilder类StringBuffer类

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的,这里介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅StringBuilder在线文档

在这里插入图片描述
我们如果要实现拼接字符串,可以使用StringBuilder类StringBuffer类的append方法,那他们有什么区别呢?
我们通过追溯原码如下所示
在这里插入图片描述
在这里插入图片描述
通过原码发现,他们的区别在于synchronized。
作用:synchronized是Java中的关键字,synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性,Java中每一个对象都可以作为锁,这是synchronized实现同步的基础。
因此我们可以知道当我们在多线程情况下使用StringBuffer类的append方法较好;在单线程情况下使用StringBuilder类的append方法较好。
注意: String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
1.String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
2.StringBuilder变为String: 调用toString()方法。
String、StringBuffer、StringBuilder的区别
1.String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
2.StringBuffer与StringBuilder大部分功能是相似的
3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试高频:HTTPS 通信流程

更多大厂面试内容可见 -> http://11come.cn 面试高频&#xff1a;HTTPS 通信流程 HTTPS 的加密流程 接下来说一下 HTTPS 协议是如何进行通信的&#xff1a; HTTPS 通信使用的 对称加密 非对称加密 两者结合的算法 HTTPS 通信时&#xff0c;会先使用 非对称加密 让通信双…

2022 E3 算法题第三题(Fair Count)

题目内容 You are given two arrays A and B consisting of N integers each. Index K is named fair if the four sums (A[0] ... A[K-1]), (A[K] ... A[N-1]), (B[0] ... B[K-1]) and (B[K] ... B[N-1]) are all equal. In other words, K is the index where the two a…

C#基础|string字符串的应用方法总结

哈喽,你好啊,我是雷工! 今天学了下关于C#string字符串的常用方法,以下为学习笔记。 01、字符串处理场景1 用邮箱注册账号时 A1、判断用户输入的邮箱是否包含“@”; A2、找到第一个匹配项所在的位置; A3、如果找到则为索引位置,否则为-1; 示例代码: static void Mai…

SQLite导出数据库至sql文件

SQLite是一款实现了自包含、无服务器、零配置、事务性SQL数据库引擎的软件库。SQLite是世界上部署最广泛的SQL数据库引擎。 SQLite 是非常小的&#xff0c;是轻量级的&#xff0c;完全配置时小于 400KiB&#xff0c;省略可选功能配置时小于250KiB。 SQLite 源代码不受版权限制。…

补档 -- 测试的分类(1)

最近有很多人私信我说: 灰灰你什么时候写测试分类阿, 本来我要开始肝性能测试的, 我一看, 奥, 之前摸鱼忘写了, 所以这里补档(叶问指着一边笑.jpg). 总览 标红的需要注意一下. 为什么要对软件测试进行分类? 软件测试是软件生命周期的一个重要环节, 具有较高的复杂性, 对于软…

C语言-字符函数与字符串函数

在C语言中&#xff0c;我们经常要对字符或是字符串进行各种操作。那C语言究竟给了我们哪些方法呢&#xff0c;本篇文章就是让大家了解对字符和字符串处理相关的知识。 目录 1.字符函数 1.1字符分类函数 1.2字符转换函数 2.字符串函数 2.1strlen函数的使用和模拟实现 2.2…

数电期末复习(二)逻辑代数基础

这里写目录标题 2.1 二值逻辑变量与基本逻辑运算2.1.1 与运算2.1.2 或运算2.1.3 非运算2.1.4 常用复合逻辑运算 2.2 逻辑函数的建立及其表示方法2.2.1 真值表表示2.2.2 逻辑函数表达式表示2.2.3 逻辑图表示方法2.2.4 波形图表示方法 2.3 逻辑代数2.3.1 逻辑代数的基本定律和恒等…

磁盘的管理

会在linux中使用硬盘 分区 格式化&#xff08;重新安装文件系统&#xff09; 挂载 硬盘的分类 1.机械硬盘 2.固态硬盘 硬盘的数据结构 扇区&#xff1a;盘片被分为多个扇形区域&#xff0c;每个扇区存放512字节的 数据 &#xff08;扇区越多容量越大&#xff09; 存放数据的…

开启智慧之旅,AI与机器学习驱动的微服务设计模式探索

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;探索设计模式的魅力&#xff1a;开启智慧…

排序 “贰” 之选择排序

目录 ​编辑 1. 选择排序基本思想 2. 直接选择排序 2.1 实现步骤 2.2 代码示例 2.3 直接选择排序的特性总结 3. 堆排序 3.1 实现步骤 3.2 代码示例 3.3 堆排序的特性总结 1. 选择排序基本思想 每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个…

前后端交互概念

前后端交互概念 1前后端分离开发概念2搭建后端环境2.1配置文件commomcommon-utilservice-utilmodelservice gitee使用 1前后端分离开发概念 前段&#xff1a;运用html、css、js和现成库&#xff0c;对数据作展示。 后端&#xff1a;运用Java和Java框架&#xff0c;提供数据或操…

Redis 逻辑过期策略设计思路

引言&#xff1a; 当我们平常使用Redis缓存的时候&#xff0c;会出现一种场景&#xff0c; redis的key到过期时间了&#xff0c;总是需要到数据库里面去查一遍数据再set回redis&#xff0c;这个时候如果数据库响应比较慢&#xff0c;那么就会造成用户等待&#xff0c;如果刚好…