【JAVA入门】Day06 - 字符串

【JAVA入门】Day06 - 字符串



一、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 来拼接字符串,可以节省时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值