Java笔记_7
一、字符串
1.1、API和API帮助文档
API(Application Programming Interface):应用程序编程接口
简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用即可。
Java API:指的就是JDK中提供的各种功能的Java类
这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。
1.2、字符串概述
java.lang.String
类代表字符串,Java程序中的所有字符串文字(例如“abc”)都为此类的对象。使用的时候不需要导包。
Java程序中的所有字符串文字都被实为此类的对象
字符串的内容是不会发生改变的,它的对象在创建后不能被更改。
1.3、string构造方法的实现和内存分析
-
直接赋值
string 变量 = "字符串"
-
new
构造方法 | 说明 |
---|---|
public String() | 创建空白字符串,不含任何内容 |
public String(String original) | 根据传入的字符串,创建字符串对象 |
public String(char[ ] chs) | 根据字符数组,创建字符串对象 |
public String(byte[ ] chs) | 根据字节数组,创建字符串对象 |
内存模型
当使用双引号直接赋值时,系统会检查该字符串再串池中是否存在
- 存在:复用
- 不存在:创建新的
非双引号直接赋值的字符串,每次赋值都会创建一个新的字符串
1.4、字符串的比较
==
号比的到底是什么
- 基本数据类型
- 比较的是具体的值
- 引用数据类型
- 比较的是地址值
字符串比较的两种方法
boolean equals
方法(要比较的字符串)
完全一样结果才是true,否则为falseboolean equalsIgnoreCase
(要比较的字符串)
忽略大小写的比较
boolean result1 = s1.equals(s2);
System.out.println(result1);
//如果返回是true则说明相同
//如果返回是false则说明是不同的
1.5、练习-用户登录
需求:已知正确的用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
package String;
import java.util.Scanner;
public class Userlogin {
public static void main(String[] args) {
String username = "Smulll";
String password = "123456";
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请输入你的用户名:");
String user = sc.next();
System.out.println("请输入你的密码:");
String pass = sc.next();
if(user.equals(username)&&pass.equals(password)){
System.out.println("欢迎进入");
break;
}else {
if(i==2){
System.out.println("你输入错误次数过多,已被锁定");
}else {
System.out.println("密码输入错误,你还剩"+(2-i)+"次机会");
}
}
}
}
}
1.6、练习-遍历字符串
public char charAt(int index)
:根据索引返回字符
public int length()
:返回此字符串的长度
数组的长度:数组名.length
字符串的长度:字符串对象.length()
package String;
import java.util.Scanner;
public class getEveryChat {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
int otherCount = 0;
for (int i = 0; i < str.length(); i++) {
char c =str.charAt(i);
if(c >='a'&&c<='z'){
smallCount++;
}else if(c >='A'&&c<='Z'){
bigCount++;
}else if(c>='0'&&c<='9'){
numberCount++;
}else {
otherCount++;
}
}
System.out.println("大写字母有"+bigCount+"个");
System.out.println("小写字母有"+smallCount+"个");
System.out.println("数字有"+numberCount+"个");
System.out.println("其他字符有"+otherCount+"个");
}
}
1.7、练习-拼接字符串
package String;
public class connect {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 3, 4};
String str = arrTostring(arr);
System.out.println(str);
}
public static String arrTostring(int[] arr) {
String result = "[";
if (arr == null) {
} else if (arr.length == 0) {
} else {
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
result = result + arr[i];
} else {
result = result + arr[i] + ",";
}
}
result = result + "]";
}
return result;
}
}
1.8、练习-金额转换
package String;
import java.util.Scanner;
public class transMoney {
public static void main(String[] args) {
int money ;
while (true){
System.out.println("请输入一个金额:");
Scanner sc = new Scanner(System.in);
money = sc.nextInt();
if (money>0&&money<=999999){
System.out.println("输入的金额是:");
break;
}else {
System.out.println("输入金额无效");
}
}
String ChineseMoney = "";
while (true){
int ge = money%10;
money = money/10;
String capitalMunber = transMoney(ge);
ChineseMoney = capitalMunber +ChineseMoney ;
if(money==0){
break;
}
}
int count = 7 - ChineseMoney.length();
for (int i = 0; i < count; i++) {
ChineseMoney = "零" + ChineseMoney;
}
String arr[] = {"佰","拾","万","仟","佰","拾","元"};
String result = "";
for (int i = 0; i < ChineseMoney.length(); i++) {
char c = ChineseMoney.charAt(i);
result = result +c +arr[i];
}
System.out.println(result);
}
public static String transMoney(int money){
String[] arr = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
return arr[money];
}
}
1.9、练习-手机号屏蔽
package String;
public class Substring {
public static void main(String[] args) {
String phoneNumber = "123123123123";
String start = phoneNumber.substring(0,3);
System.out.println(start);
String last = phoneNumber.substring(7);
System.out.println(last);
String xinxin = "****";
String all = "";
all = start + xinxin + last;
System.out.println(all);
}
}
字符串截取
String substring(int beginlndex, int endlndex)
截取
注意点:包头不包尾,包左不包右
只有返回值还是截取的小串
String substring(int beginlndex)
截取到末尾
字符串替换
String replace(旧值,新值)
替换
注意点:只有返回值才是替换之后的结果
1.10、StringBuilder的基本操作
StringBuilder可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
方法名 | 说明 |
---|---|
public StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
public StringBuilder reverse() | 反转容器中的内容 |
public int length() | 返回长度(字符出现的个数) |
public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
- 链式编程:在原来的方法导出的基础上,再次调用方法,产生一个链式方程
使用StringBuilder
的场景
- 字符串的拼接
- 字符串的反转、
检测是否为对称字符串
package String;
import java.util.Scanner;
public class symmetryString {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
String res = new StringBuilder().append(str).reverse().toString();
if (res.equals(str)){
System.out.println("这是一个对称字符串");
}else {
System.out.println("这不是一个反转字符串");
}
}
}
1.11、Stringjoiner
StringJoiner
跟StringBuilder
一样,也可以看成是一个容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。
方法名 | 说明 |
---|---|
public StringJoiner(间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
public StringJoiner(间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号 |
StringJoiner的成员方法
方法名 | 说明 |
---|---|
public StringJoiner add(添加的内容) | 添加数据,并返回对象本身 |
public int length() | 返回长度(字符出现的个数) |
public String toString() | 返回一个字符串(该字符串就是拼接之后的结果) |
1.12、字符串相关类的底层原理
扩展底层原理1:字符串存储的内存原理
- 直接赋值会复用字符串常量池中的
- new出来不会复用,而是开辟一个新的空间
扩展底层原理2:==
号比较的到底是什么?
- 基本数据类型比较数据值
- 引用数据类型比较地址值
扩展底层原理3:字符串拼接的底层原理
- 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串。
- 字符串拼接的时候有变量参与:在内存中创建了很多对象浪费空间,时间也非常慢
- 结论:如果很多字符串变量拼接,不要直接+。在底层会创建多个对象,浪费时间,浪费性能。
字符串拼接的时候,如果有变量:
JDK8以前:
- 系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接。
拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象。
JDK8版本:
- 系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。
扩展底层原理4:StringBuilder
提高效率原理图
- 所有要拼接的内容都会往
StringBuilder
中放,不会创建很多无用的空间,节约内存
扩展底层原理5:StringBuilder
源码分析
- 默认长度为16的字节数组
- 添加的内容长度小于16,直接存
- 添加的内容大于16会扩容(原来的容量*2+2)
- 如果扩容之后还不够,以实际长度为准
1.13、练习-罗马数字的两种写法
键盘录入一个字符串,
要求1∶长度为小于等于9
要求2:只能是数字将内容变成罗马数字
下面是阿拉伯数字跟罗马数字的对比关系:
Ⅰ-1、Ⅱ -2、Ⅲ- 3、Ⅳ- 4、Ⅴ - 5、Ⅵ- 6、Ⅶ- 7、Ⅷ- 8、Ⅸ- 9
注意点:
罗马数字里面是没有0的
如果键盘录入的数字包含0,可以变成" "
(长度为0的字符串)
package String;
import java.util.Scanner;
public class Roman_numerals_Text {
public static void main(String[] args) {
String str;
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
str = sc.next();
boolean flag = checkStr(str);
if(flag){
break;
}else {
System.out.println("当前字符串不符合规则,请重新输入:");
continue;
}
}
//创建一个字符串空间来存储罗马数字
/*方法一转罗马数字
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
int number = c - 48;
String s = Roman(number);
sb.append(s);
}
*/
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
String s = Roman(c);
sb.append(s);
}
System.out.println(sb);
}
//将输入的数字转化为罗马数字
//方法一:
/*
public static String Roman(int number){
String[] arr = {"","Ⅰ","Ⅱ","Ⅲ","Ⅳ","Ⅴ","Ⅵ","Ⅶ","Ⅷ","Ⅸ"};
return arr[number];
}
*/
//方法二:
public static String Roman(char number){
String str;
switch (number){
case '0'-> str = "";
case '1'-> str = "I";
case '2'-> str = "Ⅱ";
case '3'-> str = "Ⅲ";
case '4'-> str = "Ⅳ";
case '5'-> str = "Ⅴ";
case '6'-> str = "Ⅵ";
case '7'-> str = "Ⅶ";
case '8'-> str = "Ⅷ";
case '9'-> str = "Ⅸ";
default -> str = "";
/*
String str = switch (number){
case '0'-> "";
case '1'-> "I";
case '2'-> "Ⅱ";
case '3'-> "Ⅲ";
case '4'-> "Ⅳ";
case '5'-> "Ⅴ";
case '6'-> "Ⅵ";
case '7'-> "Ⅶ";
case '8'-> "Ⅷ";
case '9'-> "Ⅸ";
default -> "";
}
*/
}
return str;
}
//判断数字是否符合命名规则
public static boolean checkStr(String str){
if(str.length()>9){
return false;
}
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(c<'0'||c>'9'){
return false;
}
}
return true;
}
}
1.14、练习-调整字符串
给定两个字符串,A和B。
A的旋转操作就是将A最左边的字符移动到最右边。
例如,若A= ‘abcde’,在移动一次之后结果就是’bcdea’。
如果在若干次调整操作之后,A能变成B,那么返回True。
如果不能匹配成功,则返回false
package String;
public class moveString {
public static void main(String[] args) {
String str1 = "asdfg";
String str2 = "dfgas";
System.out.println(flag (str1,str2));
}
//判断字符串是否与旋转后的相同
public static boolean flag (String strA,String strB){
for (int i = 0; i < strA.length(); i++) {
strA = roate (strA);
if(strA.equals(strB)){
return true;
}
}
return false;
}
//方法一:通过字符串截取的方法旋转字符串
public static String roate (String str){
char first = str.charAt(0);
String end = str.substring(1);
return end+first;
}
/*
//方法二:通过字符数组的方式旋转字符串
public static String roate (String str){
char[] arr = str.toCharArray();
char first = arr[0];
for (int i = 1; i < str.length(); i++) {
arr[i-1] = arr[i];
}
arr[arr.length-1] = arr[0];
String str2 = new String(arr);
return str2;
}
*/
}