Day10字符串

一、API

1.什么是API

应用程序编程接口(已编写好的东西,直接使用)

2.Java中的API

指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来
如:Scanner,Random等

二、字符串

1.Stirng

java.lang.Stirng类代表字符串
字符串的内容不会发生改变,对象创建后不能被改变
Java中所有字符串文字都被视为此类的对象

(1)两种创建方式

1)直接赋值:Stirng name = “王一博”;
2)new:

方法名说明
public String()创建一个空白字符串对象,不含有任何内容
public String(char[] chs)根据字符数组的内容,来创建字符串对象
public String(byte[] bys)根据字节数组的内容,来创建字符串对象

(2)对字符串的“修改”

1)

	//传递字符数组
   //需求:修改字符串的内容
  //abc-->{'a','b','c'}字符串不能修改,但数组可以修改,通过修改数组,实现字符串的“修改”
  char[] chs = {'a','b','c'};
  String s4 = new String(chs);
  System.out.println(s4);

2)传递一个字节数组,根据字节数组内容再创建一个新的字符串对象

//需求:网络场景中传输数据都是字节信息
//一般把字节信息进行转换,转成字符,此时可以用到这个结构
byte[] bytes = {97,98,99,100};
String s5 = new String(bytes);
System.out.println(s5);//abcd

(3)Java的内存模型

1)栈内存:方法运行时进栈执行出栈结束
2)堆内存:new出来的对象都在这里
3)方法区:字节码文件(.class)临时存储
4)StringTable(串池):直接赋值的字符串存储在此;如果是new出来的,不在这里面。jdk7以后再堆内存里。

(4)两种创建方式的区别

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

步骤:
执行main方法,加载到栈内存中。执行程序,在栈内存创建s1,然后观察串池,串池里面有没有“abc”,如果没有创建,将地址返回给栈内存里的s1。如果已创建,直接将地址赋给s2.

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

步骤:
首先执行main方法,加载到栈内存中。执行程序,在栈内存创建chs。在堆内存中开辟空间存储数组{‘a’,‘b’,‘c’},然后将地址返回给chs。栈内存创建s1,在堆内存中开辟一小段新空间,存储“abc”,将其地址赋值给s1.创建s2,将上述过程重复一次,这个过程在堆内存里一共开辟了三小段空间,s1,s2存储的地址值并不一样。

综上:第一种比第二种更加简单,而且节约内存

(5)Java常用方法

1)==号比较

==号比什么?
基本数据类型:比的是具体的数据值
引用数据类型:比较的是地址值

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

分析:s1和s2存储的地址值,均为串池中“abc”的地址。

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

分析:s1记录的是堆里面的地址值,s2记录的是串池里的地址值

//1.键盘录入一个abc
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str1 = sc.next();
        //2.代码中定义一个字符串abc
        String str2 = "abc";
        //3.用==比较,两者一样吗?
        System.out.println(str1 == str2);//false

<1>equals方法的作用(完全一样,不能忽略大小写)
boolean equals(字符串)
<2>equalslgnoreCase(忽略大小写)
boolean equalslgnoreCase(字符串)
两者区别:是否忽略大小写
案例一:遍历字符串

public char charAt(int index)//根据索引返回字符
public int length()//返回字符串长度
//字符串长度:字符串对象.length()
//数组长度:数组名.length

案例二:金额转换
思想:反向逆推法
2135------>零佰零拾零万贰仟壹佰叁拾伍元
逆推:
零佰零拾零万贰仟壹佰叁拾伍元 —>零零零贰壹叁伍–>贰壹叁伍—>2135
数组索引:0~9

0123456789

数字当作索引去一一对应(查表法)

注意一:拼接的时候把要拼接的放到前面,避免结果反过来

moneyStr = capitalNumber+ moneyStr;

注意二:在最后输出结果时,对大写数字以及单位进行拼接

 for (int i = 0; i < moneyStr.length(); i++) {
 	 char c = moneyStr.charAt(i);
     //把大写数字和单位拼接到result
     result = result + c + arr[i];//arr存储的是单位,c时大写数字字符串的字符
        }

案例三:手机号屏蔽
方法(包左不包右)
(1)

String substring(int beginIndex,int endIndex);//截取

只有返回值才是截取的小串
(2)

String substring(int beginIndex)

默认截取到末尾

案例四:身份证信息查看
String ch类型不能直接转为int,即使只有一个元素
先获取字符,ch.charAt(0),然后可以转化成int类型

案例五:敏感词替换

String replace(旧值,新值)//替换

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

2.StringBuilder

(1)为什么学习它

字符串直接拼接100万次,速度非常慢
而用StringBuilder就会非常快

(2)概述

可以看作一个容器,创建之后内容可变

(3)两种方式拼接字符串

1)String

Sting s1 = "aaa";
Sting s2 = "bbb";
Sting s3 = "ccc";
Sting s4 = "ddd";
Sting s5 = "eee";
String s6 = s1 + s2 + s3 + s4 + s5;

过程:s1 与 s2 拼接,产生一个新的字符串,再与 s3 拼接,以此类推;在这个过程中,会产生许多没有用的字符串,浪费空间和时间
2)StringBuilder
这种方法,把s1,s2,s3,s4,s5全部放在StringBuilder容器里,在这个过程里,只有一个StringBuilder对象,效率更高

(4)常用方法

1)

public StringBuilder append(任意类型)

添加数据,并返回对象本身
2)

public StringBuilder reverse()

反转容器中的内容
3)

public int length()

返回长度(字符出现的个数)
4)

public String toString()

通过toString()可以实现把StringBuilder转换为String

(5)关于StringBuilder为空时

StringBuilder sb = new StringBuilder();
System.out.println(sb);

输出时什么都没有,因为StringBuilder是Java已经写好的类,Java底层对它做了一些处理,打印对象不是地址值而是属性值(即容器里的内容)。

(6)链式编程

当调用一个方法的时候,不需要用变量接收结果,可以继续调用其他方法
依赖前一个方法的结果再去调用其他的方法

sb.append("aaa");
sb.append("bbb");
sb.append("ccc");
sb.append("eee");

可以改写成下列形式

sb.append("aaa").append("bbb").append("ccc").append("eee");

3.StringJoiner

(1)为什么学习他

虽然StringBiulder速度快,但是有时候在使用时没那么方便。StringJoiner可以指定开始,结束,中间间隔等,更加方便

(2)概述

与StringBuilder一样,也可以看作是一个容器,创建后里面的内容是可变的。
代码编写简介,目前市场上很少有人用(JDK8出现的)

(3)构造方法

1)

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

2)

public StringJoiner(间隔符号,开始符号,结束符号);

(4)成员方法

1)添加数据,并返回对象本身

public StringJoiner add(添加内容);//添加内容只能是字符串

2)返回长度

public int length();

例如 [a,b,c],长度要把" [ " , " , " , " ]"这三个字符算进来,长度为7
3)返回一个字符串(该字符串是拼接后的结果)

public String toString();

4.字符串原理(总结)

(1)字符串存储的内存原理

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

(2)==号比较

1)基本数据类型比较数据值
2)引用数据类型比较地址值

(3)字符串拼接的底层原理

1)等号的右边没有变量(简单)
触发字符串的优化机制,在编译时已经是最终结果了
Java文件—>class文件
2)等号的右边有变量
JDK8以前会使用StringBuilder

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

过程:
<1> 堆内存的串池里生成”a“,栈内存里的s1存储a的地址值;
<2> 堆内存的串池里生成”b“,拼接时有变量的参与,先在堆内存里创建一个StringBuilder的对象,通过append()方法把s1和”b“丢放在StringBuilder对象当中,通过toString()方法把其变成字符串,赋给s2(在这个过程中会new一个String对象);
在上面的代码中,每执行一行,都会生成一个StringBuilder的对象,所以性能差。

JDK8以后字符串拼接底层原理

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

<1>先预估(预估需要时间)最终字符串的长度,并且创建一个数组;
<2>把s1,s2,s3存入数组,再把数组整体变成一个字符串;

综合
如果很多字符串变量拼接,不要直接 + 。在底层会创建多个对象,浪费时间,浪费性能
—>如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串
—>如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。

(4)StringBuilder提高效率原理图

StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
sb.append("c");
System.out,println(sb);

<1>main方法进栈,在堆内存中开辟一段空间,返回地址值赋给栈内存中的sb;
<2>调用append()方法,把a,b,c 依次添加到StringBuilder中;

常见面试题
1.

String s1 = "abc";
String s2 = "ab";
String s3 = s2 + "c";
System.out.println(s1 == s3);

分析:
s1—>记录串池中的地址值
对于s3
—>在JDK8以前,系统的底层会自动创建一个StringBuilder对象,然后会调用append方法完成拼接;拼接后,再调用toString方法转化为String类型,而toString方法的底层时直接new了一个字符串对象;他会在堆内存中新开辟一小段空间,返回地址值赋给s3;s2和s3存储的时不同地址的地址值,因为比较时不等。
—>JDK8以后,系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时产生一个新的字符串,也是new出来的。
2.

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

分析:
s1—>记录串池中的地址值
s2—>编译时,将"a" + “b” + “c"拼接成"abc”(此时代码还没有运行)
运行时,复用串池中的字符串

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

(5)StringBuilder源码分析

容量与长度注意区分
当容量不够时,StringBuilder会扩展容量,扩容:老容量 * 2 + 2 = 34
当添加的内容超过了默认扩容的容量时(即34),就以实际需要的容量为准。
总结
1.默认创建一个容量16的字节数组
2.添加内容长度小于16,直接存
3.添加内容大于16会扩容(原来容量 x 2 +2)
4.当内容大与默认的扩容容量,以实际长度为准

5.练习

(1)调整字符串

修改字符串内容的方法

<1>截取:用subString进行截取,把左边的字符截取出来拼接到右侧去;
<2>数组:可以把字符串先变成字符数组,调整字符数组里的数据,最后把字符数组变成字符串。

 String str = “abcd”;
 char[] arr = str.toCharArray();//该方法把字符串变成一个字符型数组

(2)单词长度

给一个字符串,有若干单词组成,求出最后一个单词长度
思路:
倒着遍历字符串,遇到第一个空格停止,遍历的次数即最后一个单词的长度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Heliotrope&G

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值