带你走进Java字符串的小世界

这篇具有很好参考价值的文章主要介绍了带你走进Java字符串的小世界。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一. String

1. 什么是String

2. String常用构造器

3. 字符串的判断

4. 字符串的获取

5. 字符串的转换

6. 字符串比较和替换

7. 字符串的切割

二. StringBuffer与StringBuilder

2.1 关于StringBuffer

2.1.1 定义

2.1.2 构造方法

2.2 关于StringBuffer

三. StringJoiner的使用

四. 关于常量池的面试


🐼个人主页爪哇斗罗

🐼博主介绍一名打工人

🐼签名:圣人之道,为而不争。

🐼一起交流,一起进步,一起互动。

带你走进Java字符串的小世界

带你走进Java字符串的小世界

一. String

1. 什么是String

首先,String属于引用数据类型,而不是基本数据类型。它是用来存储字符串的,使用双引号括起来的Unicode字符序列。

每个用双引号""括起来的都是属于String的一个实例。

String str = "hello"

阅读源码(Java8)会发现,String实现Serializable接口,表示字符串可以被序列化。

同时还实现Comparable接口表示字符串可以比较大小。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];// ①
}

标注①可看出Java使用char[]来存储字符串的值,Java9以后使用byte[]存储字符串。由此说明Sting底层实际上是一个字符数组

所以上述的"hello"实际上存的是['h','e','l','l','o']。

除此之外,计算机并不会存储像h,e甚至是中文这样的字符,此时就和编码表也就是字符集有关系。

指定不同的字符集,程序底层会将对应的字符按照对应的编码表进行编码存储至内存或者磁盘中。

常见的字符集编码有utf8,GBK等。utf8一个字符对应三个字节,GBK一个字符对应两个字节

2. String常用构造器

String() 构造一个空的字符串
String(byte[] arr) 将字节数组转换为字符串
String(byte[] arr, int offset, int lengh) 将字节数组部分转换为字符串
String(char[] arr) 将char字节数组转换为字符串
String(char[] arr, int offset, int length) 将char字节数组部分转换为字符串
String(String original) 字符串常量构建字符串
String(byte bytes[], int offset, int length, Charset charset) 将字节数组部分转换为指定字符集的字符串
byte[] b = {97,98,99,100};	
String str = new String(b);
System.out.println(str);//abcd

byte数组转换为String字符串会有一个解码的过程,就是将b存入内存中然后进行解码输出对应字符串得到abcd。

public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    // 解码
    this.value = StringCoding.decode(bytes, offset, length);
}

char数组转String字符串方式都和上述大同小异,这里不在赘述。

3. 字符串的判断

boolean equals(Object obj) 判断两个字符串内容是否相等
boolean equalsIgnorecase(String str) 忽略大小写判断两个对象是否相等
boolean contains(String str) 判断大字符串是否包含小字符串
​​​​​​boolean ​startsWith(String str) 判断是否以指定的字符串开头
boolean endsWIth(String str) 判断是否以指定的字符串结尾
boolean isEmpty() 判断字符串是否为空
public static void main(String[] args) {
    String s1 = "abcde";
    String s2 = "AbCde";
    String s3 = "abcde";
    //equals(): 比较两个字符串是否相等。
    System.out.println(s1.equals(s2));//true
    System.out.println(s1.equals(s3));//false
    //equalsIgnoreCase():忽略大小写比较字符串相等。
    System.out.println(s1.equalsIgnoreCase(s2));//true
    System.out.println(s1.equalsIgnoreCase(s3));//true
    //contains():是否包含指定字符串。
    System.out.println(s1.contains("bd"));//false
    //startsWith():是否以指定字符串开头
    System.out.println(s1.startsWith("ab"));//true
    // 第二个参数表示在索引为2的字符开始比较
    System.out.println(s1.startsWith("cde",2));//true
    //是否以字符串结尾
    System.out.println(s1.endsWith(s3));//true
    //是否为空
    System.out.println(s1.isEmpty());//false
}

4. 字符串的获取

length() 获取字符串的长度
charAt(inx index) 获取某个索引的字符
indexOf(int ch) 获取指定字符在字符串第一次出现的位置,可以写对应的ASCALL码值
indexOf(int ch, int fromIndex) 获取从指定的索引开始,字符出现的位置
indexOf(String str) 获取指定的字符串在原字符串的位置
indexOf(String str, int fromIndex) 获取从指定的索引开始,字符串第一次出现的位置
lastIndexOf(int ch) 获取指定字符最后一次出现的索引值
lastIndexOf(String str,int fromIndex) 获取指定字符串最后出现的索引值
subString(int start) 从指定位置开始截取字符串
subString(int start, int end) 从指定位置到指定位置截取字符串
public static void main(String[] args) {
    String str = "abcdeababcdacaeca";
    //长度
    System.out.println(str.length());//17
    //获取某个索引的字符
    System.out.println(str.charAt(1));//b
    //获取最后一个元素值
    System.out.println(str.charAt(str.length() - 1));//a
    //获取'a'第一次出现的索引值
    System.out.println(str.indexOf('a'));//0
    System.out.println(str.indexOf(97));//0
    //从第二个索引值开始,'a'第一次出现的位置
    System.out.println(str.indexOf('a', 2));//5
    //获取"bc"第一次出现的索引值
    System.out.println(str.indexOf("bc"));//1
    //从2索引开始"ad"第一次出现的索引值
    System.out.println(str.indexOf("ad", 2));//-1
    //获取'a'最后一次存储的索引值
    System.out.println(str.lastIndexOf('a'));//16
    //获取'bc'最后一次出现的索引值
    System.out.println(str.lastIndexOf("bc"));//8
    //从7索引结束前获取'a'最后一次索引值
    System.out.println(str.lastIndexOf('a', 7));//7
    System.out.println(str.lastIndexOf('c', 6));//2
    //从索引5截取到末尾
    String s1 = str.substring(5);
    System.out.println(s1);//ababcdacaeca
    //"abcdeabca" ===> "deab"
    String s2 = str.substring(3, 7);
    System.out.println(s2);
}

注意:如果没有找到都会返回-1

5. 字符串的转换

byte[] getBytes() 将字符串转换为字节数组
byte[] getBytes(String charset) 通过指定的字符集,将字符串转成字节数组
char[] toCharArray() 将字符串转成字符数组
static valueOf(char[] chs) 将字符数组转成字符串
static valueOf(Object obj) 将任意的引用数据转成字符串
toLowerCase() 转成小写
toUpperCase() 转成大写
concat(String str) 字符串连接
trim() 去除两边空格
public static void main(String[] args) {
    String s = "Ab三上悠亚";
    //String转为byte[]
    byte[] bys =s.getBytes();
    //[65, 98, -28, -72, -119, -28, -72, -118, -26, -126, -96, -28, -70, -102]
    System.out.println(Arrays.toString(bys));
    //String转为char[]
    char[] c = s.toCharArray();
    //[A, b, 三, 上, 悠, 亚]
    System.out.println(Arrays.toString(c));
    //其它大部分类型转String
    System.out.println(String.valueOf(100));//100
    System.out.println(String.valueOf(false));//false
    System.out.println(String.valueOf('a'));//a
    System.out.println(String.valueOf(3.23f));//3.23
    System.out.println(String.valueOf(c,0,3));//Ab三 从0索引开始截取三个字符
    char[] data = {'A','B','c'};
    System.out.println(String.valueOf(data));//ABc
    System.out.println(s.toLowerCase());//ab三上悠亚
    System.out.println(s.toUpperCase());//AB三上悠亚
}

6. 字符串比较和替换

replace(char old, char new) 新的字符替换旧的字符
replace(String old, Stringnew) 新的字符串替换旧的字符串
String replace(CharSequence target, CharSequence replacement) 替换指定的字符序列
int compareTo(String str) 字典比较字符串
int compareToIgnoreCase(String str) 忽略大小写比较
public static void main(String[] args) {
    String s = "abc三上悠亚abc";
    //b替换B 字符替换
    String s1 = s.replace('b', 'B');
    System.out.println(s1);//aBc三上悠亚aBc
    //三上悠亚替换为JAPAN字符串替换
    String s2 = s.replace("三上悠亚", "JAPAN");
    System.out.println(s2);//abcJAPANabc
    //替换指定的字符序列
    String s4 = "abc";
    String s5 = "abcd";
    String s6 = s.replace(s4, s5);
    System.out.println(s6);//abcd三上悠亚abcd
}

7. 字符串的切割

String[] split(String regex, int limit) 将字符串按照某种方式进行分割并指定分割多少
String[] split(String regex) 将字符串按照某种方式进行分割
public static void main(String[] args) {
    String str = "1-2-3-4-5";
    // 按照规则来切割字符串
    String[] split1 = str.split("-");
    // 按照规则来切割几段字符串
    String[] split2 = str.split("-",2);
    // [1,2,3,4.5]
    System.out.println(Arrays.toString(split1));
    // [1,2-3-4-5]
    System.out.println(Arrays.toString(split2));
}

二. StringBuffer与StringBuilder

2.1 关于StringBuffer

2.1.1 定义

作为线程不安全的可变字符序列,StringBuilder类似于String的字符缓冲区,可以看做是一个高级的String。

与String的区别就是,它是一个可变的字符序列。记住:StringBuilder是线程不安全的!!!所以在多线程场景下不可使用。

2.1.2 构造方法

StringBuilder构造

  • StringBuilder():空的构造,底层默认创建容量为16的字符缓冲区对象。
  • StringBuilder(int capacity):可以指定容量创建StringBuilder对象。
  • StringBuilder(String str):创建指定字符串的StringBuilder对象。
    StringBuilder sb = new StringBuilder();
    System.out.println(sb);//空
    System.out.println(sb.length());//0
    System.out.println(sb.capacity());//16

    StringBuilder sb1 = new StringBuilder(100);
    System.out.println(sb1);//空
    System.out.println(sb1.length());//0
    System.out.println(sb1.capacity());//100

    StringBuilder sb3 = new StringBuilder("java");
    System.out.println(sb3);//java
    System.out.println(sb3.length());//4
    System.out.println(sb3.capacity());//20

StringBuilder成员方法

  • 增加功能

    • String append(Object obj):括号中可以是任意类型

    • insert(int offset, String str):任意地方添加指定类型

  • 删除功能

    • deleteCharAt(int index) 指定位置删除对应的元素
    • delete(int index, int end)删除[index,end-1]之间的元素
  • 修改功能:

    • setCharAt(int n, char ch):
    • replace(int start,int end,String str):
  • 查询功能

    • charAt(int n):
    • int Capacity():
    • int length():
  • 反转功能

    • reverse() 反转功能
  • 截取功能

    • String substring(int start):截取指定位置一直到末尾
    • String substring(int start,int end):截取[start,end-1]范围
StringBuilder sb = new StringBuilder();
//添加
sb.append('j').append("av").append(false).append(100);//javfalse100
sb.insert(1, false);//jfalseavfalse100
//删除
sb.deleteCharAt(0);//删除第一个字符 falseavfals100
sb.delete(0, 3);//删除[0-2]的字符  seavfals100
//修改
sb.setCharAt(3, 't');//seatfalse100
sb.replace(3,7,"true");//seatruelse100
//查询元素
System.out.println(sb.charAt(6));//e
System.out.println(sb.length());//12
System.out.println(sb.capacity());//初始容量16
//截取功能
System.out.println(sb.substring(3));//truelse100
System.out.println(sb.substring(4, 7));//rue 截取[4,6]        

2.2 关于StringBuffer

StringBuffer与StringBuilder的用法是一模一样的,这里不再赘述相关方法,主要对比他们两有什么区别。

常见的String,StringBuffer,StringBuilder的面试题。

  • 可变性

    • String用final修饰,不可变
    • StringBuffer与StringBuilder都是继承AbstratBuilder类,存储的char[]并未用final修饰,是可变的
  • 线程安全性

    • String对象不可变,可以视为线程安全
    • StringBuffer加了同步锁,线程安全
    • StringBuilder方法未加同步锁,线程不安全
  • 性能

    • 每次对String进行赋值时都会产生新对象,然后将指针指向新的对象。
    • StringBuffer每次都会对对象的本身进行操作,而不是产生新的对象去引用它,相同情况下,使用StringBuilder的性能会提高,但是会有线程不安全的风险。

代码比较StringBuilder与StringBuffer的性能:

    private static void demo02() {
		StringBuilder sb = new StringBuilder("abc");
        //当前时间
		long l1  = System.currentTimeMillis();
		for(int i=0; i<100000;i++) {
			sb.append("hello");
		}
        //跑完循环
		long l2  = System.currentTimeMillis();
		System.out.println("String连接耗时:"+ (l2 -l1));
	}
    private static void demo01() {
		String s = "abc";
		//当堆空间溢出会发生OutOfMemoryError
        //当前时间
		long l1  = System.currentTimeMillis();
		for(int i=0; i<100000;i++) {
			s += "hello";
		}
        //跑完循环
		long l2  = System.currentTimeMillis();
		System.out.println("String连接耗时:"+ (l2 -l1));
	}

如何使用三者?

  • 操作少量的数据:String
  • 单线程操作大量数据:StringBuilder
  • 多线程操作大量数据:StringBuffer

三. StringJoiner的使用

上面,我们总是使用SpringBuilder去拼接字符串,使用的分割符号很多。

并且代码量相对来说也是比较多的,Java1.8给我们提供了一个StringJoiner类来专门拼接字符串。

先看一个简单的例子,将集合中的元素通过逗号分割开并输出一个字符串:

public static void main(String[] args) {
	List<Integer> integers = new ArrayList<Integer>();
	integers.add(1);
	integers.add(2);
	integers.add(3);
	integers.add(4);
	integers.add(5);
	StringBuilder stringBuilder = new StringBuilder();
	for (Integer integer : integers) {
		stringBuilder.append(integer + ",");
	}
	// 1,2,3,4,5
	System.out.println(stringBuilder.toString().substring(0, stringBuilder.length() - 1));
	}

这样的代码是不是看起来繁杂,并且只能通过手动去拼接,如果使用StringJoiner去拼接字符串就会一步到位:

public static void main(String[] args) {
	List<Integer> integers = new ArrayList<Integer>();
	integers.add(1);
	integers.add(2);
	integers.add(3);
	integers.add(4);
	integers.add(5);	
	// 序号1
	StringJoiner stringJoiner = new StringJoiner(",");
	for (Integer integer : integers) {
		stringJoiner.add(String.valueOf(integer));
	}
	// 1,2,3,4,5
	System.out.println(stringJoiner.toString());
	}

以上两段代码输出的结果都是一样的,都是1,2,3,4,5,如果我们需要输出这样的字符串[1,2,3,4,5]怎么办?其实StringJoiner也提供了这样的方法,只需要将上述的序号1代码换成:

StringJoiner stringJoiner = new StringJoiner(",","[","]");

添加两个参数,分别代表的是前缀与后缀,是不是非常简单呢,这个在开发中也是很常用的。

如果获取的数据是空的,我们呢又要给其设置一个默认的值。

那么可以使用setEmptyValue()方法就可以了:

stringJoiner.setEmptyValue("1");

拼接字符串使用StringJoiner还是挺方便的,赶快用起来吧!

四. 关于常量池的面试

先看如下所示的代码:s1与s2相等吗?

String s1 = new String(abc");
String s2 = "abc";

s1与s2虽然内容都是一样,但是两者是不相等的。

因为String是引用数据类型,如果比较相等(==),两者比较的是地址与内容是否相等。这就会引出常量池的概念。

s1是引用对象,首先会在栈内存中会开辟一个s1的引用对象的空间,而abc这个字符串常量是存在方法区常量池中。通过s1这个对象引用指向abc。

s2则是s2的一个引用指向了abc。

注意:JDK1.7之前,常量池在方法区中,JDK1.7及以后常量池放在了堆里面,我们通常指的的是1.7之前的常量池

下面来看==与equals()的比较字符串是否相等的使用。

  • == 比较的地址和内容都相等才相等
  • equals()内容相等即是相等

理解上面两句,看如下代码就会清晰很多:

    String s1 = "123";①
    String s2 = "123";②
    String s3 = new String("123");③
    System.out.println(s1==s2);//正确
    System.out.println(s1==s3);//错误

只要明白了内存分布,判断不成问题。对于①,②来说,s1,s2都在栈内存中。

对于③来说,会先在栈中开辟一个内存空间存放引用对象s3。

然后会在堆内存中重新开辟空间存放new String("123")中的String匿名对象的值123所以s1==s3是错误的!!!

对于equals()就不一样了比较的是内容是否相等,三者内容都是相等的,所以equals是true

PS: null," "的区别

null代表的是空对象,并不是字符串,可以赋给任何对象,字符串中表示只是一个引用,还没有内存空间的分配

“ ”表示引用已经指向了 一块内存空间了,是一个实际的东西,可以进行操作了,表示一个长度为0的字符串

练习一:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
String s3 = new String("hello");
String s4 = "hello";
System.out.println(s3==s4);
System.out.println(s3.equals(s4));
String s5 = "hello";
String s6 = "hello";
System.out.println(s5==s6);
System.out.println(s5.equals(s6));

答案:F T F T T T

关于字符串的拼接文章来源地址https://www.toymoban.com/news/detail-401779.html

  • 常量与常量的拼接还在常量池中
  • 常量池不可有相同的常量
  • 拼接的时候,只要存在变量都会存到堆中
  • 调用intern()方法返回常量池里面的常量
    String s1 = "hello";
    String s2 = "world";
    String s3 = "helloworld";
    System.out.println(s3==(s1+s2));//F 变量的连接存在堆中不相等
    System.out.println(s3==(s1+s2).intern());//T 获取的是值相等
    System.out.println(s3.equals(s1+s2));//T 获取内容相等
    System.out.println(s3=="hello" + "world");//T 常量与常量连接还在常量池中
    System.out.println(s3.equals("hello"+"world"));//T	内容相等	

到了这里,关于带你走进Java字符串的小世界的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 编织魔法:探索Python字符串的奇幻世界

    在当今计算机编程领域中,Python语言以其简洁、优雅和易读的特性,成为了最受欢迎的编程语言之一。其中的字符串处理是Python编程中不可或缺的技术之一。本篇博客将介绍Python字符串的基本概念,包括字符串的定义、索引和切片操作。我们将深入探讨字符串的常用方法,如

    2024年02月11日
    浏览(47)
  • 带你刷算法——数组/字符串的完全掌握(一)

    「作者主页」 :雪碧有白泡泡 「个人网站」 :雪碧的个人网站 「推荐专栏」 : ★ java一站式服务 ★ ★ 前端炫酷代码分享 ★ ★ uniapp-从构建到提升 ★ ★ 从0到英雄,vue成神之路 ★ ★ 解决算法,一个专栏就够了 ★ ★ 架构咱们从0说 ★ ★ 数据流通的精妙之道★ 给你两个

    2024年02月13日
    浏览(55)
  • 【Python】一文带你掌握数据容器之元组,字符串

    前言:如果想要传递的信息, 不被篡改 ,列表就不能满足条件了 由此当我们需要在程序内封装数据,又不希望封装的数据被篡改,那么我们就引入了元组 1.定义元组 元组定义:定义元组使用 小括号 ,且使用逗号隔开各个数据, 数据可以是不同的数据类型 元组也支持嵌套:

    2024年02月05日
    浏览(59)
  • 一文带你玩转C库中的一系列字符串函数

    作者主页: paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者: 大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于 《系统解析C语言》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将算法基础知识一网打尽,

    2024年02月13日
    浏览(48)
  • vLive带你走进虚拟直播世界

    虚拟直播是什么? 虚拟直播是基于5G+实时渲染技术,在绿幕环境下拍摄画面,通过实时抠像、渲染与合成,再推流到直播平台的一种直播技术。尽管这种技术早已被影视工业所采用,但在全民化进程中却是困难重重,面临着克服相关技术难题。该技术的应用需要具备专业导演

    2023年04月20日
    浏览(43)
  • java 字符串中插入字符串

    一、使用 StringBuilder 进行字符串处理,效率最高 输出: aaaa123abbbbcccc 效率比较高,整个过程只会产生2个对象 二、直接对字符串进行处理 此方法效率比较低,整个过程会产生4个对象 三、直接对字符串进行处理 将字符串转成数组,然后对数组进行处理,不推荐,这里就不展

    2024年02月16日
    浏览(42)
  • Java分割字符串,分割逗号字符串,分割空格

    在一些读取文件,然后对数据进行处理的过程中,我们需要获取到对应的数据,这里我有一个文本其中的数据都是用逗号进行隔开的,我需要获取到他们;

    2024年02月11日
    浏览(53)
  • Java判断一个字符串是否包含某个字符串

    开发过程中,有时会判断一个字符串是否包含某个字符串的操作,这里总结判断方法。 方式一:contains()方法         理解:contains() 方法用于判断字符串中是否包含指定的字符或字符串。(判断一个字符串是否包含某个字符串)         语法:public boolean contains(CharSequence

    2024年02月13日
    浏览(96)
  • Java中字符串占位替换、字符串拼接、字符串与Collection互转的方式

    1、String.format 最原始最基础的方式。 使用%来表示占位,后面跟上不同的标识符,用于限定这个占位符的参数类型,由jdk原生提供支持。 示例: 2、MessageFormat 如果遇到一个参数需要替换模板中多个占位的场景,更友好的方式是MessageFormat,由jdk原生提供支持。 示例: 举例:将

    2024年02月16日
    浏览(57)
  • java将list转为逗号隔开字符串,将逗号连接的字符串转成字符数组,​将逗号分隔的字符串转换为List​(Java逗号分隔-字符串与数组相互转换)

       参考:java将list转为逗号隔开字符串_51CTO博客_list转字符串逗号隔开 Java将字符串转化为数组_java 字符串转数组-CSDN博客  Java逗号分隔-字符串与数组相互转换-CSDN博客  

    2024年02月08日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包