[java] java基础-字符串篇

目录

API

String

创建字符串对象的两种方式:

Java的内存模型

字符串常量池(串池)存放地址

两种构造方法的内存分析

String的常用方法

==号比较的是什么

字符串比较(比较字符串的数据值)

遍历字符串

StringBuilder

使用场景

 构造方法

常用方法

StringJoiner

构造方法

成员方法

字符串相关的底层原理

原理1:字符串存储的内存原理

原理2:==号比较的到底是什么

原理3:字符串拼接的底层原理

拼接时没有变量

拼接时有变量

原理4:StringBuilder提高效率原理

原理5:StringBuilder源码分析

常见面试题

下列代码的运行结果(有变量)

下列代码的运行结果是(无变量)


API

API:应用程序编程接口
java API:指JDK中提供的各种功能的Java类,这些类将底层的实现封装起来,我们不需要关心这些类是如何实现的,只需要学习这些类是如何使用即可。

(API就是别人已经写好的东西,我们不用自己编写,直接使用即可)

API 例如:

  • Scanner 键盘录入
  • Random 随机数

API帮助文档:帮助开发人员更好的使用API和查询API的一个工具

API帮助文档
下载链接:https://pan.quark.cn/s/f3fd6e8bd977
提取码:meJU

用手机复制链接到夸克即可打开

找到需要的方法

String

String 是Java定义好的一个类,定义在java.lang包中,所以使用的时候不用导包

Java程序中的所有字符串文字("abc")都被称为java.lang.String类的对象

只要有字符串参加的+操作,都是字符串的拼接,字符串拼接会产生一个新的字符串

"abc"+true="abctrue";
//将abc和true进行拼接,形成新的字符串

 字符串的内容是不会发生改变的,它的对象在创建之后不能被更改

String name="123";
String address="456";
System.out.println(name+address);
//产生了3个字符串
String name="123";
name="456";
//产生了两个字符串,在常量池中创建新的字符串"456"后,
再赋值给name

创建字符串对象的两种方式:

1、直接赋值(常用)

String name="abc";

2、new 构造方法

(1)创建空白字符串,不含任何内容

空参构造,获取一个空白的字符串对象

public String () 
//""没有任何内容的字符串对象

(2)根据传入的字符串,创建字符串对象

public String (String str)

(3)根据字符数组,创建字符串对象(常用)

适用场景要求:要修改字符串的内容,可以直接修改字符数组

public String (char[] chs)

例:
char[] chs ={'a','b','c'};
String str =new String(chs);//abc

 (4)根据字节数组,创建字符串对象(常用)

适用场景要求:把字节信息转成字符串,先根据字ascii码表查询,换成对应的字符,再创建成字符串对象

在网络中传输的数据是字节

public String (byte[] chs)

例:
byte[] chs ={97,98,99};
String str =new String (chs);//abc

Java的内存模型

栈内存:方法运行的时候进栈,执行完毕出栈
堆内存:new的对象都在这里
方法区:字节码文件、临时存储

字符串常量池(串池)存放地址

JDK7以前字符串常量池在方法区,JDK7开始存放在堆内存

两种构造方法的内存分析

直接赋值:(存放在串池中,简单,节约内存)

系统会先检查该字符串在字符串常量池中是否存在,存在则复用,不存在则创建新的

new新建:

new的字符数组在堆内存中,new字符串在堆内存中开辟空间,相同字符串也会开辟空间,容易浪费内存,建议使用直接赋值

从键盘输入的数据属于new String

String s1=new String("abc");//记录堆里面的地址值
String s2="abc";//记录串池中的地址值
System.out.println(s1==s2);//false

String的常用方法

==号比较的是什么

基本数据类型:数据值

引用数据类型:地址值(String属于引用数据类型)

字符串比较(比较字符串的数据值)

boolean equals方法(要比较的字特串)  完全一样true  否则 false
boolean equalsIgnoreCase(要比较的字符串)忽略大小写的比较(英文状态的大小写 a A)

String s1=new String("abc");//记录堆里面的地址值
String s2="abc";//记录串池中的地址值
System.out.println(s1==s2);//false
//比较字符串对象中的内容是否相等
boolean result=s1.equals(s2);//true
//示例:已知正确的用户名和密码,请用程序实现模拟用户登录
//总共三次机会,登录之后,给出相应提示

public static void main(String[] args){

//1.定义两个变量记录正确的用户名和密码
String rightUsername = "zhangsan";
String rightPassword = "123456";

Scanner sc = new Scanner(System.in);
//2.键盘录入用户名和密码
for (int i = 0;i < 3; i++) {
// 0 1 2
System.out.println("请输入用户名");
String username = sc.next();
System.out.println("请输入密码");
String password = sc.next();

//3.比较
if (username.equals(rightUsername) && password.equals(rightPassword)) {
System.out.println("用户登录成功");
break;
} else {
if(i == 2){
//最后一次机会也输入错误,此时要提示账号被锁定
System.out.println("账号"+ username+"被锁定,请联系:XXX-XXXXX");
}else{
Svstem.out.println("用户登录失败,用户名或密码有误,您还剩下"+(2-i)+"次机会");//2 1 0
  }

}
}

遍历字符串

public char charAt (int index):根据索引返回字符
public int length():返回此字符串的长度

数组长度:数组名.length--属性,不加括号

字符串长度:字符串对象.length()--方法,加括号

//示例:遍历字符串
public class StringDemo5 {
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);
}

}

String substring(int beginIndex, int endIndex):截取
包头不向尾,包左不同右,只有返回值才是截取的小串
String substring( int beginIndex):截取到末尾

//示例:手机号屏蔽:
String phoneNumber=“12345671234”;
String start =phoneNumber. substring(0,3);//"123"

String end = phoneNumben.substring (7);//"1234"
String result = start+"****"+end;//123****1234

String replace(旧值,新值)替换

只有返回值才是替换后的结果

//示例:敏感词替换
String talk="你玩得真好,TMD, CNM";
String[] arr={"TMD","CNM”,“SB” "MLGB"};
for(int i=0;i<arr.length; i++)
{
talk= talk.replace(arr[i],"***");
};
//talk="你玩得真好,***,***"

StringBuilder

可以看作是一个容器,创建之后里面的内容是可变的

作用:提高字符串的操作效率

使用String进行字符串拼接时,每拼接一次就会产生一个新的字符串,浪费内存且浪费时间

而StringBuilder则是看作容器,在进行字符串拼接时不用每次都产生新的字符串,而是在原基础上进行拼接

使用场景

字符串拼接

字符串反转

 构造方法

public StringBuilder():创建一个空白可变的字符串对象,不含有任何内容

public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象

常用方法

public StringBuilder append(任意类型):添加数据,并返回对象本身

public StringBuilder reverse():反转容器中的内容

public int length():返回长度(字符出现的个数)

public String toString():实现将StringBuilder转换为String

(StringBuilder对象转为字符串)

/*
示例:对称字符串
需求:键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
对称字符串:123321、111
非对称字符串:123123
*/

public static void main(String[] args) {

//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();

//2.反转键盘录入的字符串
String result = new StringBuilder().append(str).reverse().toString();

//3.比较
if(str.equals(result)){
System.out.println("当前字符串是对称字符串");
}else{
System.out.println("当前字符串不是对称字符串");
}
}
/*
示例:拼接字符串
需求:定义一个方法,把 int数组中的数据按照指定的格式拼接成一个字符串返回。
调用该方法,并在控制台输出结果。
例如:数组为int[] arr={1,2,3};
执行方法后的输出结果为:[1,2,3]
*/

public static void main(String[] args) {

//1.定义数组
int[] arr = {1, 2, 3};

//2.调用方法把数组变成字符串
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

像上面拼接字符串的例子,使用StringBuilder,代码复杂,所以出现了StringJoiner,拼接速度快,且代码简单的方式

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

public static void main(String[] args) {
int[] arr = {1, 2, 3};
StringJoiner sj = new StringJoiner(", ", "[", "]");

for (int i = 0; i < arr.length; i++){
sj.add(arr[i] + "");
System.out.println(sj);
}
}

StringJoiner跟StringBuilder一样,也可以看成是一种容器,创建之后里面的内容是可以改变的

作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用

jdk8出现的

构造方法

public StringJoiner(间隔符号):创建一个StringJoiner对象,指定拼接时的间隔符号

public StringJoiner(间隔符号,开始符号,结束符号):创建一个StringJoiner对象,指定拼接时的间隔符号,开始符号,结束符号

没有无参构造

成员方法

public StringJoiner add(添加的内容):添加数据,并返回对象本身

public int length():返回长度(字符出现的个数)

public String to String():返回一个字符串(该字符串就是拼接之后的结果)

public static void main(String[] args) {

//1.创建对象
StringJoiner sj = new StringJoiner( delimiter: ",", prefix: "[", suffix: "]");

//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//13

//3.打印
System.out.println(sj);//[aaa,bbb,ccc]

String str = sj.toString();
System.out.println(str);//[aaa,bbb,ccc]
}

字符串相关的底层原理

原理1:字符串存储的内存原理

直接赋值会复用字符串常量池中的
new出来不会复用,而是开辟一个新的空间

原理2:==号比较的到底是什么

基本数据类型:数据值

引用数据类型:地址值

原理3:字符串拼接的底层原理

拼接时没有变量

public class Test {
public static void main(String[] args) {
String s= "a" +"b"+"c";
System.out.println(s);
}
}

拼接的时候没有变量,都是字符串。

触发字符串的优化机制。
在编译的时候就已经是最终的结果了。

//java文件
public class Test {
public static void main(String[] args) {
String s = "a"+"b"+"c";
System.out.println(s);
}
}
//编译后的class文件
public class Test {
public static void main(String[] args) {
String s ="abc";
System.out.println(s);
}
}

拼接时有变量

JDK8以前

public class Test {
public static void main(String[] args) {
String s1 = "a";
String s2= s1+"b";
//实际执行为new StringBuilder().append(s1).append("b").toString();
//toString 方法实际为new String,即上面的语句实际创建了两个对象,一个+,堆内存中两个对象
//new StringBuilder和new String
String s3= s2+"c";
//创建新的StringBuilder和String对象
//实际执行为new StringBuilder().append(s2).append("c").toString();
//toString 方法实际为new String,即上面的语句实际创建了两个对象,一个+,堆内存中两个对象
//new StringBuilder和new String
System.out.println(s3);
}
}

有变量参与,在内存中创建了很多对象,浪费空间,也非常慢

在JDK8中,会先预估拼接之后的字符串需要的空间大小,创建数组,把要拼接的内容放在数组中

如果很多字符串变量拼接,不要直接+,在底层会创建多个对象,浪费时间,浪费性能

建议使用StringBuilder或者StringJoiner

有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串

如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。

原理4:StringBuilder提高效率原理

public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
sb.append("c");
System.out.printIn(sb);
}
}

 所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,节约内存

原理5:StringBuilder源码分析

默认创建一个长度为16的字节数组
添加的内容长度小于16,直接存
添加的内容大于16会扩容(原来的容量*2+2)
如果扩容之后还不够,以实际长度为准

public class Test4 {
public static void main(Stringl] args) {
StringBuilder sb = new StringBuilder();
//容量:最多装多少
//长度:已经装了多少
System.out.printIn(sb.capacity());//16
system.out.printin(sb.length());//0

sb.append("abc");
System.out.printin(sb.capacity());//16
System.out.printIn(sb.length());//3
}
}
public class Test4 {
public static void main(Stringl] args) {
StringBuilder sb = new StringBuilder();
//容量:最多装多少
//长度:已经装了多少
System.out.printIn(sb.capacity());//16
system.out.printin(sb.length());//0

sb.append("abcdefghijklmnopqrstuvwxyz");
System.out.printin(sb.capacity());//34
System.out.printIn(sb.length());//26
}
}
public class Test4 {
public static void main(Stringl] args) {
StringBuilder sb = new StringBuilder();
//容量:最多装多少
//长度:已经装了多少
System.out.printIn(sb.capacity());//16
system.out.printin(sb.length());//0

sb.append("abcdefghijklmnopqrstuvwxyz0123456789");
System.out.printin(sb.capacity());//36
System.out.printIn(sb.length());//36
}
}

常见面试题

下列代码的运行结果(有变量)

public class Test3 {
public static void main(String[] args) {
String s1 ="abc";//记录串池中的地址值
String s2="ab";
String s3 = s2 +"c";//新new出来的对象,堆地址
System.out.println(s1 == S3);//false
}
}

字符串拼接的时候,如果有变量
JDK8以前:系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接。拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象。
JDK8版本:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。

所以无论是高版本或者低版本的JDK,有变量的字符串进行拼接,都会创建新的对象,存放在堆地址中

下列代码的运行结果是(无变量)

public class Test4 {
public static void main(String[] args){
String s1 ="abc"; //记录串池中的地址值
String s2="a" +"b"+"c"; //复用串池中的字符串
Svstem.out.println(s1 == s2);  //true
}
}

在编译的时候,就会将"a"+"b"+"c"拼接为"abc",所以s1和s2指向串池中的同一个字符串,地址值相同

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

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

相关文章

C# 多线程同步(Mutex | Semaphore)

Mutex: 用于保护临界区&#xff0c;确保同一时间只有一个线程能够访问共享资源&#xff1b; Semaphore: 允许同时有多个线程访问共享资源&#xff0c;但会限制并发访问的数量。 Mutex运行输出 Semaphore运行输出 namespace SyncThreadDemo {internal class Program{static stri…

易语言模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

ThinkPhp伪静态设置后,访问静态资源也提示找不到Controller

ThinkPhp没有配置伪静态时&#xff0c;除了默认的IndexController能访问&#xff0c;其他路由Controller都访问不到&#xff0c;提示404错误。配置了伪静态后就解决了这个问题。 但是当我的ThinkPhp后台项目中有静态资源放在public目录&#xff08;或子目录&#xff09;中需要…

C#编译报错: error CS1069: 未能在命名空间“System.Windows.Markup”中找到类型名“IComponentConnector”

文章目录 问题现象解决方案 问题现象 一个以前使用.NET Framwork 3.0框架开发的项目&#xff0c;在框架升级到.NET Framwork 4.7.2后&#xff0c; 如下代码&#xff1a; #pragma checksum "..\..\XpsViewer.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}&qu…

在宝塔安装部署mindoc

MinDoc简介 MinDoc 是一款针对IT团队开发的简单好用的文档管理系统。 MinDoc 的前身是 SmartWiki 文档系统。SmartWiki 是基于 PHP 框架 laravel 开发的一款文档管理系统。因 PHP 的部署对普通用户来说太复杂&#xff0c;所以改用 Golang 开发。可以方便用户部署和实用。 开…

2025寒假备战蓝桥杯01---朴素二分查找的学习

文章目录 1.暴力方法的引入2.暴力解法的思考 与改进3.朴素二分查找的引入4.朴素二分查找的流程5.朴素二分查找的细节6.朴素二分查找的题目 1.暴力方法的引入 对于下面的这个有序的数据元素的组合&#xff0c;我们的暴力解法就是挨个进行遍历操作&#xff0c;一直找到和我们的这…

计算机毕业设计hadoop+spark+hive图书推荐系统 豆瓣图书数据分析可视化大屏 豆瓣图书爬虫 知识图谱 图书大数据 大数据毕业设计 机器学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

麒麟操作系统服务架构保姆级教程(十四)iptables防火墙四表五链和防火墙应用案例

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 防火墙在运维工作中有着不可或缺的重要性。首先&#xff0c;它是保障网络安全的关键防线&#xff0c;通过设置访问控制规则&#xff0c;可精准过滤非法网络流量&#xff0c;有效阻挡外部黑客攻击、恶…

微服务学习-Nacos 注册中心实战

1. 注册中心的设计思路 1.1. 微服务为什么会用到注册中心&#xff1f; 服务与服务之间调用需要有服务发现功能&#xff1b;例如订单服务调用库存服务&#xff0c;库存服务如果有多个&#xff0c;订单服务到底调用那个库存服务呢&#xff08;负载均衡器&#xff09;&#xff0…

机器人奇点:从宇树科技看2025具身智能发展

近年来&#xff0c;随着人工智能和机器人技术的飞速发展&#xff0c;具身智能&#xff08;Embodied Intelligence&#xff09;逐渐成为科技领域的热门话题。具身智能不仅赋予了机器人感知、决策和执行的能力&#xff0c;还通过与物理世界的交互&#xff0c;推动了人工智能从“离…

Tensor 基本操作1 unsqueeze, squeeze, softmax | PyTorch 深度学习实战

本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 目录 创建 Tensor常用操作unsqueezesqueezeSoftmax代码1代码2代码3 argmaxitem 创建 Tensor 使用 Torch 接口创建 Tensor import torch参考&#xff1a;https://pytorch.org/tutorials/beginn…

(详细)Springboot 整合动态多数据源 这里有mysql(分为master 和 slave) 和oracle,根据不同路径适配不同数据源

文章目录 Springboot 整合多动态数据源 这里有mysql&#xff08;分为master 和 slave&#xff09; 和oracle1. 引入相关的依赖2. 创建相关配置文件3. 在相关目录下进行编码&#xff0c;不同路径会使用不同数据源 Springboot 整合多动态数据源 这里有mysql&#xff08;分为maste…

03垃圾回收篇(D3_垃圾收集器的选择及相关参数)

目录 学习前言 一、收集器的选择 二、GC日志参数 三、垃圾收集相关的常用参数 四、内存分配与回收策略 1. 对象优先在Eden分配 2. 大对象直接进入老年代 3. 长期存活的对象将进入老年代 4. 动态对象年龄判定 5. 空间分配担保 学习前言 本章主要学习垃圾收集器的选择及…

Hadoop特点和HDFS命令

Hadoop的特点 高扩展性: 可以根据数据量的增长进行扩展,可以扩展到数千台机器&#xff0c;每个机器都可以提供本地计算和存储资源 高容错性: 自动保存数据的多个副本&#xff0c;并能够在硬件故障的情况下重新分配计算任务&#xff0c;从而确保系统的高可用性和数据的不丢失。…

LetsWave脑电数据简单ERP分析matlab(一)

LetsWave是基于matlab的一款工具包&#xff0c;类似eeglab&#xff0c;也可以对数据进行预处理。习惯使用eeglab做数据预处理的&#xff0c;可以先在eeglab中做预处理&#xff0c;然后可以保存为*.set格式&#xff0c;最后在letswave中画图。 letswave下载地址&#xff1a;htt…

深度学习|表示学习|卷积神经网络|通道 channel 是什么?|05

如是我闻&#xff1a; 在卷积神经网络&#xff08;CNN&#xff09;中&#xff0c;channel&#xff08;通道&#xff09; 是指输入或输出数据的深度维度&#xff0c;通常用来表示输入或输出的特征类型。 通道的含义 输入通道&#xff08;Input Channels&#xff09;&#xff1a;…

【机器学习】机器学习引领数学难题攻克:迈向未知数学领域的新突破

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 一、引言 在数学的浩瀚领域中&#xff0c;存在着诸多长期未解的难题&#xff0c;这些难题犹如高耸的山峰&#xff0c;吸引着无数数…

2024年美赛C题评委文章及O奖论文解读 | AI工具如何影响数学建模?从评委和O奖论文出发-O奖论文做对了什么?

模型假设仅仅是简单陈述吗&#xff1f;允许AI的使用是否降低了比赛难度&#xff1f;还在依赖机器学习的模型吗&#xff1f;处理题目的方法有哪些&#xff1f;O奖论文的优点在哪里&#xff1f; 本文调研了当年赛题的评委文章和O奖论文&#xff0c;这些问题都会在文章中一一解答…

Ubuntu如何安装redis服务?

环境&#xff1a; Ubuntu22.04 WSL2 问题描述&#xff1a; 如何安装redis服务&#xff1f; 解决方案&#xff1a; 1.在 Linux 上&#xff08;如 Ubuntu/Debian&#xff09;安装 1.通过包管理工具安装 Redis 服务器&#xff1a; sudo apt update sudo apt install redis…

最新-CentOS 7安装1 Panel Linux 服务器运维管理面板

CentOS 7安装1 Panel Linux 服务器运维管理面板 一、前言二、环境要求三、在线安装四、离线安装1.点击下面1 Panel官网链接访问下载&#xff0c;如未登录或注册&#xff0c;请登录/注册后下载2.使用将离线安装包上传至目标终端/tem目录下3.进入到/tem目录下解压离线安装包4.执行…