【JAVA入门】Day06 - 字符串

【JAVA入门】Day06 - 字符串


文章目录

  • 【JAVA入门】Day06 - 字符串
    • 一、API
    • 二、字符串
      • 2.1 创建 String 对象的方式
      • 2.2 字符串内存模型
    • 三、字符串的相关操作
      • 3.1 字符串的比较
      • 3.2 遍历字符串
      • 3.3 统计字符出现次数
      • 3.4 拼接字符串
      • 3.5 字符串反转
    • 四、StringBuilder
      • 3.1 构造方法
      • 3.2 常用方法
      • 3.3 链式编程
    • 五、StringJoiner
    • 六、字符串拼接的底层原理


一、API

        API(Application Programming Interface)中文名称叫做应用程序编程接口。通俗理解,API 就是别人写好的东西,我们不需要自己编写,直接使用即可。
        Java API 就是 JDK 中提供的各种功能类的 Java 类,这些类将底层的实现封装了起来,我们无需关注这些类如何实现,只需学习这些类如何使用即可。

二、字符串

        java.lang.String 类代表了字符串,也就是说,Java 程序中所有的字符串都是此类的对象。而 java.lang 是不需要特地导入的,可以直接使用该包下的相关类。
        字符串的内容是不能发生改变的,它的对象在创建后不能被更改。如果将两个字符串进行拼接等操作,只会产生新的字符串,即新对象。

String name1 = "赵四";
String name2 = "陈坤";
System.out.println(name1 + name2);   // 产生了一个新的字符串

2.1 创建 String 对象的方式

  • 第一种方式是以直接赋值的形式创建:
String s1 = "哥们儿我创建了一个字符串"
  • 第二种方式是用 new 的方式来创建一个字符串对象:
public String();					// 创建空白字符串,不含任何内容
public String(String original);		// 根据传入的字符串,创建字符串对象
public String(char[] chs);			// 根据字符数组,创建字符串对象
public String(byte[] chs);			// 根据字节数组,创建字符串对象

例:

String s1 = new String();           	// 空串,内容为 ""
String s2 = new String("abc");			// 用一个字符串作为参数传递给 String类,再由它创建一个字符串对象

char[] chs = {'a', 'b','c','d'};
String s3 = new String(chs);			// 根据字符数组中的内容,创建一个字符串"abcd"

byte[] bytes = {97, 98, 99, 100};
String s5 = new String(bytes);			// 根据字节数组中的内容,创建一个字符串"abcd",这里的 abcd 是根据字节数组里的数字,从 ASCii 码表里查出来而得知的,先从 ASCii 码中找到对应的字符,再用之生成字符串

2.2 字符串内存模型

        Java 中其实还存在过一块内存空间,名叫 StringTable(串池),用于专门存放字符串常量。从 JDK7 版本开始,这块空间从方法区中挪到了堆内存。

public class StringDemo {
	public static void main(String[] args) {
		String s1 = "abc";
		String s2 = "abc";
	}
}

在这里插入图片描述
        当使用双引号直接赋值的方式创建字符串,系统会检查该字符串在串池中是否已存在。若不存在,系统会首先把字符串存储到串池中,然后给予一个地址值;若存在了,也就是第二次赋同内容的串(即完全一致)时,系统还会从这个地址去寻找刚才的串,这就是串的复用

        如果使用 new 空间的方式创建数组,比如先创建了一个 chs 字符数组,再用这个字符数组作为参数传递给 String 类的构造函数,生成字符串对象,则如下所示。

public class StringDemo {
	public static void main(String[] args) {
		char[] chs = {'a', 'b', 'c'};
		String s1 = new String(chs);
		String s2 = new String(chs);
	}
}

        既然使用到了字符数组,就一定会在堆里开辟了一块空间来存储它,而生成的字符串也会存放在堆中。
在这里插入图片描述
        每生成一个字符串,就会再开辟一块新空间来存放,不存在复用。
        因此在创建字符串时,我们一般选用第一种方法,节省内存空间。

三、字符串的相关操作

3.1 字符串的比较

        如果直接使用 == 号来进行比较字符串,是存在一定问题的。下面的例子可以解释。

String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);	//true
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2);	//false

        为什么同样都是"abc",两次比较的结果不同?
        这就要讲到 == 比较的原理:
        如果 == 两边都是基本数据类型,那么进行比较的就是具体的值;但如果 == 两边是引用数据类型,那么进行比较的是左右两侧内容的地址值。
        因此,字符串如果使用 == 比较,那么就是在比较左右两串的地址值。而,Java 中的字符串存在复用情况,因此两个直接赋值得到的字符串相等时,其地址也是同一个;而通过字符数组生成的字符串,和直接赋值得到的串明显不是同一个地址值(上面已经解释了),所以最后输出了 false。
        因此,Java 中专门提供了方便字符串比较内容的函数。

  • boolean equals(要比较的字符串)                                           完全一样结果才是true,否则为false。
  • boolean equalsIgnoreCase(要比较的字符串)                        忽略大小写的比较。
public class StringDemo1 {
	public static void main(String[] args) {
		String s1 = new String("abc");
		String s2 = "abc";
		boolean result1 = s1.equals(s2);  // 调用equals 函数比较内容
		System.out.println(s1 == s2);	  // false
		System.out.println(result1);	  // true
	}
}
public class StringDemo2 {
	public static void main(String[] args) {
		String s1 = "ABC";
		String s2 = "abc";
		boolean result1 = s1.equals(s2);  // 调用equals 函数比较内容
		boolean result2 = s1.equalsIgnoreCase(s2);	// 调用 equalsIgnoreCase 函数比较内容,忽略大小写
		System.out.println(result1);	  // false
		System.out.println(result2);	  // true
	}
}

3.2 遍历字符串

需求:从键盘录入一个字符串,使用程序实现在控制台遍历该字符串。
        在字符串类中,提供了两个方便的方法:

  • public char charAt(int index):根据索引返回字符。
  • public int length():返回此字符串的长度。
import java.util.Scanner;

public class StringDemo1 {
	public static void main(String[] args) {
		//1.键盘录入字符串
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个字符串");
		String str = sc.next();
		//2.进行遍历
		for(int i = 0; i < str.length(); i++) {
			//i 依次索引字符串的每一个字符
			char c = str.charAt(i);
			System.out.println(c);
		}
	}
}

3.3 统计字符出现次数

需求:键盘录入一个字符串,统计该字符串中大小写字母、数字出现的次数。

import java.util.Scanner;

public class StringDemo2 {
	public static void main(String[] args) {
		//1.键盘录入字符串
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个字符串");
		String str = sc.next();
		//2.进行遍历,同时进行统计
		int upperCount = 0;
		int lowCount = 0;
		int numCount = 0;
		for(int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if(c >= 'a' && c <= 'z') {
				lowCount++;
			}
			else if(c >= 'A' && c <= 'Z') {
				upperCount++;
			}
			else if(c >= '0' && c <= '9') {
				numCount++;
			}
		}
		System.out.println("大写字母有" + upperCount + "个,小写字母有" + lowCount + "个,数字有" + numCount + "个。");
	}
}

3.4 拼接字符串

需求:定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:
        数组为 int[] arr = {1, 2, 3};执行方法后的输出结果为:[1, 2, 3]。

public class StringDemo3 {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3};
		String str = arrToString(arr);
		System.out.println(str);
	}

	// 写了一个方法,把数组变成字符串
	public static String arrToString(int[] arr) {
		if(arr == null) {
			return "";
		}
		if(arr.length == 0) {
			return "[]";
		}
		String result = "[";
		for(int i = 0; i < arr.length; i++) {
			//i 索引 arr[i] 元素
			if(i < arr.length - 1) {
				result = result + arr[i] + ",";
			}else{
				result = result + arr[i];
			}
		}
		result = result + "]";
	}
}

3.5 字符串反转

需求:定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法,控制台输出反转字符串。

import java.util.Scanner;

public class StringDemo4 {
	public static void main(String[] args) {
		//1.键盘录入字符串
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个字符串");
		String str = sc.next();
		//2.调用字符串反转方法
		System.out.println(reverser(str));
	}
	public static String reverser(String str) {
		String result = "";
		for(int i = str.length() - 1; i >= 0 ; i--) {
			char c = str.charAt(i);
			result = result + c;
		}
		return result;
	}
}

四、StringBuilder

        StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的,所以它也被叫做“可变字符串”。它的作用就是提高字符串的操作效率。

3.1 构造方法

  • public StringBuilder()                                创建一个空白可变字符串对象,不含有任何内容。
  • public StringBuilder(String str)                  根据字符串的内容,来创建可变字符串对象。
StringBuilder sb = new StringBuilder("abc");

3.2 常用方法

  • public StringBuilder append(任意类型)                添加数据,并返回对象本身。添加的数据可以是任何类型,它们都会被转成字符串。
  • public StringBuilder reverse()                              反转容器中的内容。
  • public int length()                返回长度(字符出现的个数)。
  • public String toString()                通过toString() 就可以实现把 StringBuilder 转换为 String。
  • System.out.println(sb)                StringBuilder是 JAVA 已经写好的类,在它的底层逻辑上,通过打印方法打印出的是它的属性值而不是地址值(一般情况打印对象都是打印地址值),因此 StringBuilder 对象可以直接打印。

3.3 链式编程

        我们都知道,Java 给 String 对象提供了很多实用的方法,而某些方法的返回值还是一个字符串,这就说明我们可以通过反复调用的办法简化程序,这就是链式编程

int len = getString().substring(1).replace("A","Q").length();

【例】判断对称字符串
需求:键盘接受一个字符串,程序判断该字符串是否是对称字符串(如:123321、111),并在控制台打印是或不是。

public class StringBuilderDemo5 {
	public static void main(String[] args) {
	//1.键盘录入一个字符串
	Scanner sc = new Scanner(System.in);
	System.out.println("请输入一个字符串");
	String str = sc.next();
	
	//2.反转键盘录入的字符串
	String reverseStr = new StringBuilder().append(str).reverse().toString();  //链式编程,直接用类调用内部函数生成sb对象并反转转为字符串赋给新串,省去起对象名字的步骤了

	//3.判断是不是等于原字符串
	if(str.equals(reverseStr)){
		System.out.println("是对称字符串。");
	}else{
		System.out.println("不是对称字符串。");
	}
	}
}

【例】拼接字符串
需求:定义一个方法,把 int 数组中的数据按照指定格式拼接成一个字符串返回,并在控制台输出结果。例如:数组是 int[] arr = {1, 2, 3};执行方法后输出:[1, 2, 3]。

public class StringBuilderDemo6 {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3};
		String str = arrToString(arr);
		System.out.println(str);
	}

	public static String arrToString(int[] arr) {
			StringBuilder sb = new StringBuilder();
		sb.append("[");
	
		for(int i = 0; i < arr.length;i++) {
			if(i == arr.length - 1){
				sb.append(arr[i]);
		}else{
				sb.append(arr[i]).append(", ");
		}
	}
		sb.append("]");
		return sb.toString();
	}
}

五、StringJoiner

        StringJoiner 是 JAVA 新版本新提出的一种类,它的特点就是拼接字符串速度快且方便。

  • 构造方法:
    public StringJoiner(间隔符号)                                                创建一个StringJoiner对象,指定拼接时的间隔符号。
    public StringJoiner(间隔符号, 开始符号, 结束符号)                创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号。
StringJoiner sj = new StringJoiner("---");
// 1---2---3
StringJoiner sj = new StringJoiner(", ","[", "]");
// [1, 2, 3]
  • 成员方法:
    public StringJoiner add(添加的内容)                添加数据并返回对象本身
    public int length()                                              返回长度(字符出现的个数)
    public String toString()                                      返回一个字符串(该字符串就是拼接之后的结果字符串)
String Joiner sj = new StringJoiner("---");
sj.add("aaa").add("bbb").add("ccc");    // 这里的参数只能填字符串,不如sb方便
System.out.println(sj);	 // 同 sb 一样,sj 也可以直接 sout
// aaa---bbb---ccc
int len = sj.length();
System.out.println(len);	// 15
// 注意,length()函数统计的是sj容器中的字符总个数,包含间隔符号、开始符号和结束符号,当然也包含空格

六、字符串拼接的底层原理

        字符串拼接有两种底层方式。其一如下:

String s = "a" + "b" + "c";
System.out.println(s);

这种拼接方式的特点是,没有变量参与加法,都是字符串,这个时候触发字符串优化机制,编译时就已经是最终结果,相当于如下写法:

String s = "abc";
System.out.println(s);

所以说s = “a”+“b”+"c"和s = "abc"本质上是一样的,二者如果同时出现,也会指向同一个地址值(复用)。
其二是有变量参与:

String s1 = "a";
String s2 = s1 + "b";
String s3 = s2 + "c";
System.out.println(s3);

这种拼接方式的特点是,系统预估字符串拼接后的长度,提前创建一段空间存放字符串(也就是产生了一个新的字符串)。但是这个预估是需要时间成本的,因此我们在拼接字符串时,一般还是使用 StringBuilder 来拼接字符串,可以节省时间。

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

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

相关文章

束测后台实操文档2-OpenWrt

束测后台实操文档1-PVE、PBS 上面文&#xff0c;把proxmox装好并添加好PBS上的镜像存储空间后&#xff0c;还原已经做好的镜像基本上就可以在已有的镜像下开展工作了。 调试的PVE环境一般两个网口&#xff0c;一个外网wan&#xff0c;一个子网lan&#xff0c;虚拟机一般在lan…

体验Photoshop:无需下载,直接在浏览器编辑图片

搜索Photoshop时&#xff0c;映入眼帘的是PS软件下载&#xff0c;自学PS软件需要多长时间&#xff0c;学PS软件有必要报班吗...PS软件的设计功能很多&#xff0c;除了常见的图像处理功能外&#xff0c;还涉及图形、文本、视频、出版等。不管你是平面设计师&#xff0c;UI/UX设计…

可变参数

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;还可以定义可变参数。可变参数也称不定长参数&#xff0c;即传入函数中的实际参数可以是任意多个。 定义可变参数时&#xf…

植物大战僵尸杂交版破解C++实现

文章目录 前言准备工作&#xff1a;基地址与偏移UI界面设计和绑定项目模板总览图生成与实现信号处理1、阳光值更新:BTN12、三种钱币值更新:BTN2-BTN43、冷却刷新:BTN54、锁定阳光&#xff1a;check15、无冷却&#xff1a;check26、OnTimer&#xff08;&#xff09;和OnClose&am…

Linux上传文件

在finalshell中连接的Linux系统中&#xff0c;输入命令rz然后选择windows中的文件即可。

透视茅台股东大会三大关键词:稳定、竞争力、创新

执笔 | 尼 奥 编辑 | 扬 灵 “让我们携手共同致力于茅台的稳定、健康、可持续发展。”上任刚满一个月的贵州茅台党委书记、董事长张德芹&#xff0c;在5月29日的贵州茅台酒股份有限公司2023年度股东大会上迎来首秀。 张德芹在40多分钟脱稿演讲与30多分钟互动环节中&#x…

TiDB学习9:Ti Cloud简介

目录 1. 为什么选择TiDB 2. 多租户 3. TiDB架构 4. 什么是TiDB Cloud 5. TiDB Cloud Provider Region 6. TiDB Cloud 入门 6.1 在浏览器中打开TiDB Cloud 6.2 创建您的账户 6.3 Developer Tier 与Dedicated Tier 6.3.1 Developer Tier 6.3.2 Dedicated Tier 6.3.2.…

项目纪实 | 版本升级操作get!GreatDB分布式升级过程详解

某客户项目现场&#xff0c;因其业务系统要用到数据库新版本中的功能特性&#xff0c;因此考虑升级现有数据库版本。在升级之前&#xff0c;万里数据库项目团队帮助客户在本地测试环境构造了相同的基础版本&#xff0c;导入部分生产数据&#xff0c;尽量复刻生产环境进行升级&a…

【NVM】nvm常用命令,切换node版本命令

nvm常用的命令&#xff0c;切换node版本命令 nvm 查看支持安装的node版本 nvm list available nvm安装指定版本node nvm install 版本号 例如&#xff1a;nvm install 10.24.1 nvm查看本机安装所有node版本 nvm list nvm切换node版本 nvm use 10.24.1 检测当前node版本 node -…

玄机平台应急响应—Linux日志分析

1、前言 啥是日志呢&#xff0c;日志就是字面意思&#xff0c;用来记录你干了啥事情。日志大体可以分为网站日志和系统日志&#xff0c;网站日志呢就是记录哪个用户在哪里什么时候干了啥事&#xff0c;以及其它的与网站相关的事情。系统日志呢&#xff0c;就是记录你的电脑系统…

动态分配函数参数用二级指针的作用

文章目录 前言一、案例 前言 在一些情况下&#xff0c;我们需要在函数内部动态地分配内存来存储结构体&#xff0c;并且需要在函数外部访问该结构体。在这种情况下&#xff0c;可以使用二级指针作为函数参数来实现动态内存分配&#xff0c;并且在函数外部使用指针访问结构体。…

12V转19V4A升压恒压WT3207

12V转19V4A升压恒压WT3207 WT3207是款高效的PWM升压控制器&#xff0c;采用SO-8封装设计。该控制器经过优化以适应低输入电压应用&#xff0c;具有从5V至36V的广泛输入电压范围&#xff0c;适用于需要提高12V、15V和19V系统电压的场合&#xff0c;特别是对于两节或三节锂离子电…

Apache Doris 基础 -- 数据表设计(数据模型)

Versions: 2.1 1、模型概览 本主题从逻辑角度介绍了Doris中的数据模型&#xff0c;以便您可以在不同的业务场景中更好地使用Doris。 基本概念 本文主要从逻辑的角度描述Doris的数据模型&#xff0c;旨在帮助用户在不同的场景更好地利用Doris。 在Doris中&#xff0c;数据在…

GEE 10m近实时 LULC 数据集Dynamic World

Google Earth Engine 和 Dynamic World Google 利用其地球引擎&#xff08;Earth Engine&#xff09;和人工智能&#xff08;AI&#xff09;平台技术&#xff0c;推出了 Dynamic World 数据库&#xff0c;能够提供接近实时的全球土地环境数据。Dynamic World 是基于 Google Ear…

【Gradle】Gradle的本地安装和使用

目录 1、Gradle 的安装 2、集成 IntelliJ IDEA 3、使用 Gradle Gradle 完全兼容 Maven 和 Ivy 仓库&#xff0c;你可以从中检索依赖也可以发布你的文件到仓库中&#xff0c;Gradle 提供转换器能把 Maven 的构建逻辑转换成 Gradle 的构建脚本。 1、Gradle 的安装 Gradle 的…

卷积网络迁移学习:实现思想与TensorFlow实践

摘要&#xff1a;迁移学习是一种利用已有知识来改善新任务学习性能的方法。 在深度学习中&#xff0c;迁移学习通过迁移卷积网络&#xff08;CNN&#xff09;的预训练权重&#xff0c;实现了在新领域或任务上的高效学习。 下面我将详细介绍迁移学习的概念、实现思想&#xff0c…

【Qt】Qt界面美化指南:深入理解QSS样式表的应用与实践

文章目录 前言&#xff1a;1. 背景介绍2. 基本语法3. QSS 设置方式3.1. 设置全局样式3.2. 从文件加载样式表3.3. 使用 Qt Designer 编辑样式 总结&#xff1a; 前言&#xff1a; 在当今这个视觉至上的时代&#xff0c;用户界面&#xff08;UI&#xff09;的设计对于任何软件产…

嵌入式Linux复制剪切删除指令详解

指令操作 1. cp 复制指令 a. 用法&#xff1a;cp [ 选项 ] [ 源文件或目录 ] [ 目标文件或目录 ]&#xff1b; b. 用途&#xff1a;用于复制文件或目录&#xff1b; c. 通常情况下&#xff0c;复制的都不是空文件夹&#xff0c;所以直接使用 cp 复制空文件会失败&#xff0…

[ROS 系列学习教程] 建模与仿真 - Xacro 语法

ROS 系列学习教程(总目录) 本文目录 一、属性与属性块二、数学表达式三、宏3.1 宏的基本使用3.2 属性块做为宏的入参3.3 任意数量元素做为宏的入参3.4 指定多个块元素的处理顺序3.5 宏嵌套3.6 默认参数3.7 局部属性 四、Rospack 命令五、包含其他 xacro 文件六、条件语句七、YA…

C#中接口的显式实现与隐式实现及其相关应用案例

C#中接口的显式实现与隐式实现 最近在学习演化一款游戏项目框架时候&#xff0c;框架作者巧妙使用接口中方法的显式实现来变相对接口中方法进行“密封”&#xff0c;增加实现接口的类访问方法的“成本”。 接口的显式实现和隐式实现&#xff1a; 先定义一个接口&#xff0c;接口…