【Java 基础】字符串 String 概述、相关方法

字符串 String


目标:熟悉字符串的相关方法,并掌握其用法。

一、概述

定义

字符串或串(String)是由数字、字母、下划线组成的一串字符。

  • jdk1.8及以前String使用的是char数组,jdk1.9及以后使用的是byte数组。

核心源码:
① jdk8:
jdk1.8及以前
② jdk9:
在这里插入图片描述

  • 通过查看源码,我们可以得知,String字符串的本质是数组。
  • 我们以jdk15为例,进行介绍。

二、Latin1 与 UTF-16

  • 与String类底层相关的两种编码方式,分别为Latin1和UTF-16,它们分别代表两个特殊类:StringLatin1StringUTF16,负责处理不同编码的字符串,提供不同的方法。我们在使用字符串相关方法时,会先在String类内进行判断,决定使用哪个类所提供的相应方法,然后进入相应方法,经过逐次返回,最终将结果返回给我们。

Latin1

  • Latin1ISO-8859-1的别名,有些环境下写作Latin-1。
  • ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致。
  • 0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

StringLatin1类 (byte[] → char[]) 数组转换方法——inflate

inflate方法

  • 该方法将byte[]转化为char[]。
  • 对每个元素(字节)进行取低8位操作,转化为字符后,依次赋值,并整合为字符数组。

UTF-16

  • UTF-16Unicode字符编码五层次模型的第三层字符编码表(Character Encoding Form,也称为
    “storage format”)的一种实现方式。
  • 即把Unicode字符集的抽象码位映射为16位长的整数(即码元)的序列,用于数据存储或传递。
  • Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。

StringUTF16类 (byte[] → char[]) 数组转换方法——getChars

getChars方法

  • 该方法依次调用取字符方法getChar,同样可以将byte[]转化为char[]。

三、相关方法

1、equals

  • equals方法用于将字符串与指定的对象比较,String 类中重写了 equals方法用于比较两个字符串的内容是否相等。

  • equals的用法如下:
    equals

equals(Object anObject)、创建字符串的相关事项

① 不使用 new 关键字创建字符串:

String str = "abc";
String str2 = "abc";
System.out.println(str==str2);
System.out.println(str.equals(str2));

运行结果如下:
情况一

② 使用 new 关键字创建字符串:

String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3==str4);
System.out.println(str3.equals(str4));

运行结果如下:
情况一

使用 == 和 equals() 比较字符串。
String 中 == 比较引用地址是否相同,equals() 比较字符串的内容是否相同:

String s1 = "Hello";              // String 直接创建
String s2 = "Hello";              // String 直接创建
String s3 = s1;                   // 相同引用
String s4 = new String("Hello");  // String 对象创建
String s5 = new String("Hello");  // String 对象创建
 
s1 == s1;         // true, 相同引用
s1 == s2;         // true, s1 和 s2 都在公共池中,引用相同
s1 == s3;         // true, s3 与 s1 引用相同
s1 == s4;         // false, 不同引用地址
s4 == s5;         // false, 堆中不同引用地址
 
s1.equals(s3);    // true, 相同内容
s1.equals(s4);    // true, 相同内容
s4.equals(s5);    // true, 相同内容

常量池、堆

编译阶段:
① 常量池中的每一项常量都是一个表,都有自己对应的类型。
② String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值。该表只存储文字字符串值,不存储符号引用。
③ JVM的常量池最多可放65535个项。第0项不用。最后一项最多只能是65534(下标值)。而每一项中,若是放一个UTF-8的常量串,其长度最长是:65535个字节(不是字符)。

运行时阶段:
① String内部是以char数组的形式存储,数组的长度是int类型,String允许的最大长度就是Integer.MAX_VALUE,即2147483647。
② 由于java中的字符是以16位存储的,因此大概需要4GB的内存才能存储最大长度的字符串。

  • equals源码如下所示:
    equals的源码

2、equalsIgnoreCase

  • equalsIgnoreCase方法将字符串与指定的字符串比较,并且忽略大小写。
    equalsIgnoreCase

equalsIgnoreCase(String anotherString)

String str1 = "I love you";
String str2 = "I LOVE YOU";
System.out.println("比较字符串是否相等, 并忽略字母大小写:" + str1.equalsIgnoreCase(str2));

运行结果如下所示:
运行结果

3、compareTo

  • compareTo 方法用于将 Number 对象与方法的参数字符串进行比较,并返回目标字符串与源字符串,字符值间隔值(差值)之和。
  • compareTo 的用法如下:
    compareTo

compareTo(String anotherString)

String str = "I love you";
System.out.println(str.compareTo("I love u"));
System.out.println(str.compareTo("I love you"));
System.out.println(str.compareTo("I love you, haha!"));
System.out.println(str.compareTo("123"));
System.out.println(str.compareTo("sasdhasf5433^%"));

运行结果如下所示:
运行结果

4、compareToIgnoreCase

  • compareToIgnoreCase 方法与compareTo 方法类似,唯一的区别是,该方法忽略大小写。
  • compareToIgnoreCase 的用法如下:

compareToIgnoreCase

compareToIgnoreCase(String str)

String str1 = "I love you 123";
String str2 = "I LOVE YOU 123";
String str3 = "I LOVE YOU 124";
System.out.println(str1.compareToIgnoreCase(str2));
System.out.println(str1.compareToIgnoreCase(str3));

运行结果

5、toCharArray

  • toCharArray 方法将字符串转为字符数组
  • toCharArray 的用法如下:
    toCharArray

toCharArray()

String str = "I love you";					//定义字符串
char[] chs = str.toCharArray();				//使用该方法,将字符串转化为字符串
System.out.println(Arrays.toString(chs));	//使用Arrays数组辅助类,转化为保留数组格式的字符串,并打印输出

代码运行结果如下:
运行结果

  • toCharArray 源码如下所示:
    toCharArray源码
  • 可以根据字符集的不同,调用不同类的toChars方法,从而将字符串转化为字符数组

6、charAt

  • charAt 方法取出字符串中的某个字符
  • charAt 的用法如下:
    charAt

7、toUpperCase / toLowerCase

① toUpperCase()

  • toUpperCase 方法将字符串中所有小写字母转换为大写字母
  • toUpperCase 的用法如下:
    toUpperCase
String str = "abcdefg";
System.out.println("处理前的字符串:"+str);
str = str.toUpperCase();
System.out.println("处理后的字符串:"+str);

运行结果如下:
运行结果

② toLowerCase()

  • toLowerCase方法将字符串中所有大写字母转换为小写字母
  • toLowerCase的用法如下:

toLowerCase

String str = "AAAAA";
System.out.println("处理前的字符串:"+str);
str = str.toLowerCase();
System.out.println("处理后的字符串:"+str);

运行结果如下:
运行结果

  • 这里,我们对它们的源码,暂不做深入探讨。

8、trim

trim()

  • trim方法用于修剪字符串,去除字符串首尾空白字符,并返回处理后的字符串。
  • trim的用法如下:
    trim
String str = "    \n  \t  \r    abcdefg      QWERTYU      23333";
System.out.println("处理前的字符串:"+str);
str = str.trim();
System.out.println("处理后的字符串:"+str);

以上代码运行结果如下:
代码运行结果

  • trim源码如下所示:
    进行字符集判断

  • 首先,String类本身的trim()方法,会使用isLatin1()方法对字符集进行判断,这里用到了三目运算符。

  • 当字符集为Latin1时,将字符串的值作为参数传递并调用StringLatin1类的trim()方法,同样若条件不满足(当字符集为UTF16时),则调用StringUTF16类的trim()方法。

  • StringLatin1类的trim()方法:
    StringLatin1类的trim()方法

  • StringUTF16类的trim()方法:
    StringUTF16类的trim()

  • 两种字符集的trim方法思想基本一致,首先定义“串首索引值st”、“串尾索引值len”。

  • 第一个循环从串首向后搜索,直到找到了字节码大于空格值的字符位置(空格是最大的 “空位值”),否则将使得串首索引值st不断增加(后移)。

  • 第二个循环从串尾向前搜索,同理,否则将使得串尾索引值st不断减少(前移)。

  • 一旦完成两次循环,视为完成寻找。根据索引,重构字符串,并返回结果值

  • 【注】:这是一张Unicode字符列表,可以看到:空格是最大的 “空位值”。

Unicode

9、indexOf / lastIndexOf

  • indexOf / lastIndexOf 方法主要用于寻找第一次 / 最后一次 出现某字符 / 字符串的位置索引,并返回相应索引值;若没有找到,则返回-1。
  • indexOf 从串首向串尾搜索,而lastIndexOf从串尾向串首搜索。
    indexOf / lastIndexOf
    我们本例使用字符串如下:
String str = "abcdefg a13231";

① indexOf(String str) / indexOf(int ch)

  • 这种寻找方式,默认开始搜寻位置为串首。
String str = "abcdefg a13231";
System.out.println("第一次出现字符'a'的索引(下标):"+str.indexOf('a'));
System.out.println("第一次出现字符串'efg'的索引(下标):"+str.indexOf("efg"));

运行结果如下:
运行结果

② indexOf(String str, int fromIndex) / indexOf(int ch, int fromIndex)

  • 这种寻找方式,可以任意指定开始搜寻位置。
String str = "abcdefg a13231";
System.out.println("第一次出现字符'a'的索引(下标),指定从3开始向后进行搜索:"+str.indexOf('a',3));
System.out.println("第一次出现字符串'efg'的索引(下标),指定从6开始向后进行搜索:"+str.indexOf("efg",6));

运行结果如下:
运行结果

③ lastIndexOf(String str) / lastIndexOf(int ch)

  • 这种寻找方式默认开始位置为串尾。
String str = "abcdefg a13231";
System.out.println("最后一次出现字符'a'的索引(下标):"+str.lastIndexOf('a'));
System.out.println("最后一次出现字符串'efg'的索引(下标):"+str.lastIndexOf("efg"));

运行结果如下:
运行结果

④ lastIndexOf(String str, int fromIndex) / lastIndexOf(int ch, int fromIndex)

  • 这种寻找方式,可以任意指定开始搜寻位置。
String str = "abcdefg a13231";
System.out.println("最后一次出现字符'a'的索引(下标),指定从3开始向前进行搜索:"+str.lastIndexOf('a',3));
System.out.println("最后一次出现字符串'efg'的索引(下标),指定从3开始向前进行搜索:"+str.lastIndexOf("efg",6));

运行结果如下:运行结果

  • indexOf / lastIndexOf 的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

10、substring

  • substring方法用于截取字符串,根据输入的参数,截取字串并返回。
    substring可接受参数
  • 可以看到,该方法有两个重载。
  • substring的用法如下:

① substring(int beginIndex, int endIndex)

  • substring 的这种重载,用于截取字符串,索引间的子串。
  • 第一个参数为起始处索引,第二个参数为结束处索引。
String str = "我很开心!";
System.out.println("处理前的字符串:"+str);
str = str.substring(1,4);
System.out.println("处理后的字符串:"+str);

以上代码运行结果如下:
运行结果

  • substring方法的这种重载的源码如下所示:
    substring源码

  • 首先,定义length记录字符串长度。

  • 其次,使用checkBoundsBeginEnd方法检查传入参数是否满足范围要求。

  • 而后,使用if进行判断,如果字串等于字符串本身,则不做截取,直接返回该字符串。

  • 若不满足if,则记录应写个长度,并根据字符集,调用相关字符集串类中的newString方法重构字符串,并返回相应的结果值。

② substring(int beginIndex)

  • substring 这种重载,用于截取字符串,从传入索引值到字符串末尾的字串。
  • substring 的用法如下:
String str = "我很开心!";
System.out.println("处理前的字符串:"+str);
str = str.substring(2);
System.out.println("处理后的字符串:"+str);

以上代码运行结果如下:
运行结果

  • substring方法这种重载的源码如下所示:
    substring源码
  • 可以看到,该方法的底层帮我们调用了上一种方法,第一个参数为输入的起始值,第二个参数默认为字符串长度。

11、concat

  • concat 方法用于连接两个字符串,该方法对不修改原本的引用,而是生成新的字符串。
  • concat的用法如下:
    concat

concat(String str)

String str1 = "abc";
System.out.println(str1.concat("123"));
System.out.println(str1);

以上代码运行结果如下:
运行结果

  • concat的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

12、replace

  • replace用于将字符串中所有的一种字符,替换为另一种字符。
  • replace的用法如下:
    replace可接受参数

replace(char oldChar, char newChar)

  • replace 用于 替换字符串中的所有某种字符。
String str = "abcdefaaag";
System.out.println("处理前的字符串:"+str);
str = str.replace('a','R');
System.out.println("处理后的字符串:"+str);

运行结果如下所示:
运行结果

  • replace的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

13、valueOf

  • valueOf 方法将传入参数转为字符串
  • valueOf 可接受参数如下所示:
    valueOf可接受参数

valueOf(int i / char c / long l / float f / double b / boolean / char[] data)

System.out.println(String.valueOf(1));
System.out.println(String.valueOf('a'));
System.out.println(String.valueOf(System.currentTimeMillis()));
System.out.println(String.valueOf(3189.756));
System.out.println(String.valueOf(true));
System.out.println(String.valueOf(new char[]{'p','e','a','r'}));

运行结果如下:
在这里插入图片描述

  • valueOf的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

14、contains

  • contains方法用于判断字符串中,是否包含子串。
  • contains的使用方法如下:
    contains

contains(CharSequence s)

String str = "abcdefaaag";
boolean flag = str.contains("asda");
System.out.println(flag);

运行结果如下所示:
contains

String str = "abcdefaaag";
boolean flag = str.contains("aaa");
System.out.println(flag);

运行结果如下所示:
contains

  • contains源码:
    contains源码

15、join

  • join 方法可将数组、集合以某拼接符拼接到一起形成新的字符串。
    join

join(CharSequence delimiter, Char[] chs)

  • join 的使用方法如下:
String[] strs = {"A","b","d","3"};
String str = String.join(",",strs);
System.out.println(str);

运行结果如下所示:
运行结果

16、length

  • length 方法用于获取字符串的长度,返回值类型为int。
    length

length()

  • length 的使用方法如下:
String str = "abcdefaaag";
System.out.println("字符串str长度为:"+str.length());

运行结果如下:
运行结果

17、isEmpty

  • isEmpty 方法用于 检查字符串长度是否长度为0。

isEmpty()

//字符串长度为0
String str1 = "";
//引用指向null
String str2 = null;
//打印结果
System.out.println("字符串长度为0:" + str1.isEmpty());
System.out.println("引用指向null:" + str2.isEmpty());

运行结果如下:
运行结果

  • 可以看到当为null时,抛出了空指针异常(NullPointerException),这证明了引用指向null,并非指向一个字符串对象,null代表没有指向任何内存空间

  • isEmpty()源码:
    isEmpty

  • 可以看到它的源码,检查长度是否为0。

18、split

  • split 方法用于按模式分割字符串,将其转化为字符数组。
    split

19、startsWith / endsWith

  • startsWith / endsWith 方法分别用于检测字符串是否以某串作为开头 / 结尾。
    startsWith
  • startsWith 方法检测串首是否匹配,endsWith 方法检测串尾是否匹配。
    endsWith

四、练习

Ⅰ:将一个字符串进行反转,例如:“abcd” → “dcba”。

public String reverseString(String str) {
   char[] chs = str.toCharArray();
   for (int i = 0; i < chs.length/2; i++) {
       chs[i] = (char) (s[i] ^ chs[chs.length-i-1]);
       chs[chs.length-i-1] = (char) (chs[i] ^ chs[chs.length-i-1]);
       chs[i] = (char) (s[i] ^ chs[chs.length-i-1]);
   }
   return String.valueOf(s);
}
String str = "abcdefg";
System.out.println("处理前的字符串:"+str);
System.out.println("处理前的字符串:"+ reverseString(str));

运行结果

Ⅱ:判定输入的一个字符串是否全为数字,使用两种方式完成。

①普通方法

 public boolean isNumStr(String str){
        char[] chs = str.toCharArray();
        if(str == null||str==""){
            return false;
        }
        for(int i =0 ;i < chs.length;i++){
            if(!(chs[i] > '0' && chs[i] < '9')){
                return false;
            }
        }
        return true;
    }

②正则表达式

public static boolean isNumStr(String str){
    if(str.matches("[0-9]+")){
        return true;
    }
    return false;
}

判断字符串:

String str = "abcdefg a13231";
String str2 = "13231";
System.out.println("是否为纯数字字符串:"+isNumStr(str));
System.out.println("是否为纯数字字符串:"+isNumStr(str2));

运行结果如下所示:
运行结果

Ⅲ:输入一个由小写字符组成的字符串,统计出每个字符出现的次数

public void lowCaseLetterInString() {
	// 仅含有小写字母的字符串
	String str = "asnhfahfrlkanwdflkad";
	// 转换为字符数组
	char[] chs = str.toCharArray();
	// 计数用int数组
	int[] count = new int[26];
	// 计数
	for (int i = 0; i < chs.length; i++) {
		count[chs[i] - 'a'] += 1;
	}
	// 遍历
	int max = -1;
	int pos = 0;
	for (int j = 0; j < chs.length; j++) {
		if (count[j] > max) {
			max = count[j];
			System.out.println(max);
		}
		System.out.println((char) ('a' + j) + "出现的次数:" + count[j]);
	}
	System.out.println("出现频率最高的字母为:" + (char) ('a' + pos));
}

运行结果如下所示:
在这里插入图片描述

Ⅳ:去除标签字符串

去除标签字符串

public void grabInfo() {
	String str4 = "<h1>這是測試結果</h1><p>test a</p>";
	String pattern3 = "(<\\w+>)|(</\\w+>)";
	String str5 = str4.replaceAll(pattern3,"");
	System.out.println(str5);
}

运行结果如下所示:
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值