Java基础(十)字符串相关类

news/2024/3/28 22:16:34/文章来源:https://blog.csdn.net/zhufei463738313/article/details/130334769

1 字符串相关类之不可变字符序列:String

1.1 String的特性

  • java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如"hello" )都可以看作是实现此类的实例。

  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。

  • 字符串String类型本身是final声明的,意味着我们不能继承String。

  • String对象的字符内容是存储在一个字符数组value[]中的。"abc" 等效于 char[] data={'h','e','l','l','o'}
    请添加图片描述

//jdk8中的String源码:
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[]; //String对象的字符内容是存储在此数组中/** Cache the hash code for the string */private int hash; // Default to 0
  • private意味着外面无法直接获取字符数组,而且String没有提供value的get和set方法。
  • final意味着字符数组的引用不可改变,而且String也没有提供方法来修改value数组某个元素值
  • 因此字符串的字符数组内容也不可变的,即String代表着不可变的字符序列。即,一旦对字符串进行修改,就会产生新对象。
  • JDK9只有,底层使用byte[]数组。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { @Stableprivate final byte[] value;
}//官方说明:... that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.//细节:... The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.
  • Java 语言提供对字符串串联符号(“+”)以及将其他对象转换为字符串的特殊支持(toString()方法)。

1.2 String的内存结构

1.2.1 概述

因为字符串对象设计为不可变,那么所以字符串由常量池来保存很多常量对象。

JDK6中,字符串常量池在方法区。JDK7开始,就移到堆空间,直到目前JDK17版本。

举例内存结构分配:

请添加图片描述

1.2.2 练习类型1:拼接

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);
// 内存中只有一个"hello"对象被创建,同时被s1和s2共享。

对应内存结构为:(以下内存结构以JDK6为例绘制):
请添加图片描述
进一步:
请添加图片描述

Person p1 = new Person();
p1.name =Tom";Person p2 = new Person();
p2.name =Tom";System.out.println(p1.name.equals( p2.name)); //
System.out.println(p1.name == p2.name); //
System.out.println(p1.name == "Tom"); //

请添加图片描述

1.2.3 练习类型2:new

String str1 = “abc”; 与 String str2 = new String(“abc”);的区别?
请添加图片描述
str2 首先指向堆中的一个字符串对象,然后堆中字符串的value数组指向常量池中常量对象的value数组。

  • 字符串常量存储在字符串常量池,目的是共享。

  • 字符串非常量对象存储在堆中。

练习:

String s1 = "javaEE";
String s2 = "javaEE";
String s3 = new String("javaEE");
String s4 = new String("javaEE");System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false

请添加图片描述
练习:String str2 = new String(“hello”); 在内存中创建了几个对象?

两个

1.2.4 练习类型3:intern()

  • String s1 = “a”;

说明:在字符串常量池中创建了一个字面量为"a"的字符串。

  • s1 = s1 + “b”;

说明:实际上原来的“a”字符串对象已经丢弃了,现在在堆空间中产生了一个字符串s1+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能。

  • String s2 = “ab”;

说明:直接在字符串常量池中创建一个字面量为"ab"的字符串。

  • String s3 = “a” + “b”;

说明:s3指向字符串常量池中已经创建的"ab"的字符串。

  • String s4 = s1.intern();

说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的"ab"字符串赋值给s4。

练习:

String s1 = "hello";
String s2 = "world";
String s3 = "hello" + "world";
String s4 = s1 + "world";
String s5 = s1 + s2;
String s6 = (s1 + s2).intern();System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s4 == s5);
System.out.println(s3 == s6);

结论:

(1)常量+常量:结果是常量池。且常量池中不会存在相同内容的常量。

(2)常量与变量 或 变量与变量:结果在堆中

(3)拼接后调用intern方法:返回值在常量池中

练习:

@Test
public void test01(){String s1 = "hello";String s2 = "world";String s3 = "helloworld";String s4 = s1 + "world";//s4字符串内容也helloworld,s1是变量,"world"常量,变量 + 常量的结果在堆中String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是变量,变量 + 变量的结果在堆中String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果System.out.println(s3 == s4);//falseSystem.out.println(s3 == s5);//falseSystem.out.println(s3 == s6);//true
}@Test
public void test02(){final String s1 = "hello";final String s2 = "world";String s3 = "helloworld";String s4 = s1 + "world";//s4字符串内容也helloworld,s1是常量,"world"常量,常量+常量结果在常量池中String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是常量,常量+ 常量 结果在常量池中String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果System.out.println(s3 == s4);//trueSystem.out.println(s3 == s5);//trueSystem.out.println(s3 == s6);//true
}@Test
public void test01(){String s1 = "hello";String s2 = "world";String s3 = "helloworld";String s4 = (s1 + "world").intern();//把拼接的结果放到常量池中String s5 = (s1 + s2).intern();System.out.println(s3 == s4);//trueSystem.out.println(s3 == s5);//true
}

练习:下列程序运行的结果:

public class TestString {public static void main(String[] args) {String str = "hello";String str2 = "world";String str3 ="helloworld";String str4 = "hello".concat("world");String str5 = "hello"+"world";System.out.println(str3 == str4);//falseSystem.out.println(str3 == str5);//true}
}

concat方法拼接,哪怕是两个常量对象拼接,结果也是在堆。

练习:下列程序运行的结果:

public class StringTest {String str = new String("good");char[] ch = { 't', 'e', 's', 't' };public void change(String str, char ch[]) {str = "test ok";ch[0] = 'b';}public static void main(String[] args) {StringTest ex = new StringTest();ex.change(ex.str, ex.ch);System.out.print(ex.str + " and ");//System.out.println(ex.ch);}
}

1.3 String的常用API-1

1.3.1 构造器

  • public String() :初始化新创建的 String对象,以使其表示空字符序列。
  • String(String original): 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
  • public String(char[] value) :通过当前参数中的字符数组来构造新的String。
  • public String(char[] value,int offset, int count) :通过字符数组的一部分来构造新的String。
  • public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。
  • public String(byte[] bytes,String charsetName) :通过使用指定的字符集解码当前参数中的字节数组来构造新的String。

举例:

//字面量定义方式:字符串常量对象
String str = "hello";//构造器定义方式:无参构造
String str1 = new String();//构造器定义方式:创建"hello"字符串常量的副本
String str2 = new String("hello");//构造器定义方式:通过字符数组构造
char chars[] = {'a', 'b', 'c','d','e'};     
String str3 = new String(chars);
String str4 = new String(chars,0,3);//构造器定义方式:通过字节数组构造
byte bytes[] = {97, 98, 99 };     
String str5 = new String(bytes);
String str6 = new String(bytes,"GBK");
public static void main(String[] args) {char[] data = {'h','e','l','l','o','j','a','v','a'};String s1 = String.copyValueOf(data);String s2 = String.copyValueOf(data,0,5);int num = 123456;String s3 = String.valueOf(num);System.out.println(s1);System.out.println(s2);System.out.println(s3);
}

1.3.2 String与其他结构间的转换

字符串 --> 基本数据类型、包装类:

  • Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
  • 类似地,使用java.lang包中的Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。

基本数据类型、包装类 --> 字符串:

  • 调用String类的public String valueOf(int n)可将int型转换为字符串
  • 相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换。

字符数组 --> 字符串:

  • String 类的构造器:String(char[]) 和 String(char[],int offset,int length) 分别用字符数组中的全部字符和部分字符创建字符串对象。

字符串 --> 字符数组:

  • public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。

  • public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。

字符串 --> 字节数组:(编码)

  • public byte[] getBytes() :使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
  • public byte[] getBytes(String charsetName) :使用指定的字符集将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。

字节数组 --> 字符串:(解码)

  • String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
  • String(byte[],int offset,int length) :用指定的字节数组的一部分,即从数组起始位置offset开始取length个字节构造一个字符串对象。
  • String(byte[], String charsetName ) 或 new String(byte[], int, int,String charsetName ):解码,按照指定的编码方式进行解码。

代码示例:

@Test
public void test01() throws Exception {String str = "中国";System.out.println(str.getBytes("ISO8859-1").length);// 2// ISO8859-1把所有的字符都当做一个byte处理,处理不了多个字节System.out.println(str.getBytes("GBK").length);// 4 每一个中文都是对应2个字节System.out.println(str.getBytes("UTF-8").length);// 6 常规的中文都是3个字节/** 不乱码:(1)保证编码与解码的字符集名称一样(2)不缺字节*/System.out.println(new String(str.getBytes("ISO8859-1"), "ISO8859-1"));// 乱码System.out.println(new String(str.getBytes("GBK"), "GBK"));// 中国System.out.println(new String(str.getBytes("UTF-8"), "UTF-8"));// 中国
}

1.4 String的常用API-2

String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。

1.4.1 系列1:常用方法

(1)boolean isEmpty():字符串是否为空
(2)int length():返回字符串的长度
(3)String concat(xx):拼接
(4)boolean equals(Object obj):比较字符串是否相等,区分大小写
(5)boolean equalsIgnoreCase(Object obj):比较字符串是否相等,不区分大小写
(6)int compareTo(String other):比较字符串大小,区分大小写,按照Unicode编码值比较大小
(7)int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
(8)String toLowerCase():将字符串中大写字母转为小写
(9)String toUpperCase():将字符串中小写字母转为大写
(10)String trim():去掉字符串前后空白符
(11)public String intern():结果在常量池中共享

	@Testpublic void test01(){//将用户输入的单词全部转为小写,如果用户没有输入单词,重新输入Scanner input = new Scanner(System.in);String word;while(true){System.out.print("请输入单词:");word = input.nextLine();if(word.trim().length()!=0){word = word.toLowerCase();break;}}System.out.println(word);}@Testpublic void test02(){//随机生成验证码,验证码由0-9,A-Z,a-z的字符组成char[] array = new char[26*2+10];for (int i = 0; i < 10; i++) {array[i] = (char)('0' + i);}for (int i = 10,j=0; i < 10+26; i++,j++) {array[i] = (char)('A' + j);}for (int i = 10+26,j=0; i < array.length; i++,j++) {array[i] = (char)('a' + j);}String code = "";Random rand = new Random();for (int i = 0; i < 4; i++) {code += array[rand.nextInt(array.length)];}System.out.println("验证码:" + code);//将用户输入的单词全部转为小写,如果用户没有输入单词,重新输入Scanner input = new Scanner(System.in);System.out.print("请输入验证码:");String inputCode = input.nextLine();if(!code.equalsIgnoreCase(inputCode)){System.out.println("验证码输入不正确");}}

1.4.2 系列2:查找

(11)boolean contains(xx):是否包含xx
(12)int indexOf(xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1
(13)int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
(14)int lastIndexOf(xx):从后往前找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1
(15)int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。

	@Testpublic void test01(){String str = "尚硅谷是一家靠谱的培训机构,尚硅谷可以说是IT培训的小清华,JavaEE是尚硅谷的当家学科,尚硅谷的大数据培训是行业独角兽。尚硅谷的前端和UI专业一样独领风骚。";System.out.println("是否包含清华:" + str.contains("清华"));System.out.println("培训出现的第一次下标:" + str.indexOf("培训"));System.out.println("培训出现的最后一次下标:" + str.lastIndexOf("培训"));}

1.4.3 系列3:字符串截取

(16)String substring(int beginIndex) :返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
(17)String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。

@Test
public void test01(){String str = "helloworldjavaatbegin";String sub1 = str.substring(5);String sub2 = str.substring(5,10);System.out.println(sub1);System.out.println(sub2);
}@Test
public void test02(){String fileName = "快速学习Java的秘诀.dat";//截取文件名System.out.println("文件名:" + fileName.substring(0,fileName.lastIndexOf(".")));//截取后缀名System.out.println("后缀名:" + fileName.substring(fileName.lastIndexOf(".")));
}

1.4.4 系列4:和字符/字符数组相关

(18)char charAt(index):返回[index]位置的字符
(19)char[] toCharArray(): 将此字符串转换为一个新的字符数组返回
(20)static String valueOf(char[] data) :返回指定数组中表示该字符序列的 String
(21)static String valueOf(char[] data, int offset, int count) : 返回指定数组中表示该字符序列的 String
(22)static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String
(23)static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String

	@Testpublic void test01(){//将字符串中的字符按照大小顺序排列String str = "helloworldjavaatbegin";char[] array = str.toCharArray();Arrays.sort(array);str = new String(array);System.out.println(str);}@Testpublic void test02(){//将首字母转为大写String str = "jack";str = Character.toUpperCase(str.charAt(0))+str.substring(1);System.out.println(str);}@Testpublic void test03(){char[] data = {'h','e','l','l','o','j','a','v','a'};String s1 = String.copyValueOf(data);String s2 = String.copyValueOf(data,0,5);int num = 123456;String s3 = String.valueOf(num);System.out.println(s1);System.out.println(s2);System.out.println(s3);}

1.4.5 系列5:开头与结尾

(24)boolean startsWith(xx):测试此字符串是否以指定的前缀开始
(25)boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
(26)boolean endsWith(xx):测试此字符串是否以指定的后缀结束

	@Testpublic void test1(){String name = "张三";System.out.println(name.startsWith("张"));}@Testpublic void test2(){String file = "Hello.txt";if(file.endsWith(".java")){System.out.println("Java源文件");}else if(file.endsWith(".class")){System.out.println("Java字节码文件");}else{System.out.println("其他文件");}}

1.4.6 系列6:替换

(27)String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 不支持正则。
(28)String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
(29)String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
(30)String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

@Test
public void test1(){String str1 = "hello244world.java;887";//把其中的非字母去掉str1 = str1.replaceAll("[^a-zA-Z]", "");System.out.println(str1);String str2 = "12hello34world5java7891mysql456";//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉String string = str2.replaceAll("\\d+", ",").replaceAll("^,|,$", "");System.out.println(string);}

1.5 常见算法题目

**题目1:**模拟一个trim方法,去除字符串两端的空格。

	public String myTrim(String str) {if (str != null) {int start = 0;// 用于记录从前往后首次索引位置不是空格的位置的索引int end = str.length() - 1;// 用于记录从后往前首次索引位置不是空格的位置的索引while (start < end && str.charAt(start) == ' ') {start++;}while (start < end && str.charAt(end) == ' ') {end--;}if (str.charAt(start) == ' ') {return "";}return str.substring(start, end + 1);}return null;}@Testpublic void testMyTrim() {String str = "   a   ";// str = " ";String newStr = myTrim(str);System.out.println("---" + newStr + "---");}

**题目2:**将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”

	// 方式一:public String reverse1(String str, int start, int end) {// start:2,end:5if (str != null) {// 1.char[] charArray = str.toCharArray();// 2.for (int i = start, j = end; i < j; i++, j--) {char temp = charArray[i];charArray[i] = charArray[j];charArray[j] = temp;}// 3.return new String(charArray);}return null;}// 方式二:public String reverse2(String str, int start, int end) {// 1.String newStr = str.substring(0, start);// ab// 2.for (int i = end; i >= start; i--) {newStr += str.charAt(i);} // abfedc// 3.newStr += str.substring(end + 1);return newStr;}// 方式三:推荐 (相较于方式二做的改进)public String reverse3(String str, int start, int end) {// ArrayList list = new ArrayList(80);// 1.StringBuffer s = new StringBuffer(str.length());// 2.s.append(str.substring(0, start));// ab// 3.for (int i = end; i >= start; i--) {s.append(str.charAt(i));}// 4.s.append(str.substring(end + 1));// 5.return s.toString();}@Testpublic void testReverse() {String str = "abcdefg";String str1 = reverse3(str, 2, 5);System.out.println(str1);// abfedcg}

**题目3:**获取一个字符串在另一个字符串中出现的次数。
比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数

	// 第3题// 判断str2在str1中出现的次数public int getCount(String mainStr, String subStr) {if (mainStr.length() >= subStr.length()) {int count = 0;int index = 0;// while((index = mainStr.indexOf(subStr)) != -1){// count++;// mainStr = mainStr.substring(index + subStr.length());// }// 改进:while ((index = mainStr.indexOf(subStr, index)) != -1) {index += subStr.length();count++;}return count;} else {return 0;}}@Testpublic void testGetCount() {String str1 = "cdabkkcadkabkebfkabkskab";String str2 = "ab";int count = getCount(str1, str2);System.out.println(count);}

**题目4:**获取两个字符串中最大相同子串。比如:
str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm”
提示:将短的那个串进行长度依次递减的子串与较长的串比较。

	// 第4题// 如果只存在一个最大长度的相同子串public String getMaxSameSubString(String str1, String str2) {if (str1 != null && str2 != null) {String maxStr = (str1.length() > str2.length()) ? str1 : str2;String minStr = (str1.length() > str2.length()) ? str2 : str1;int len = minStr.length();for (int i = 0; i < len; i++) {// 0 1 2 3 4 此层循环决定要去几个字符for (int x = 0, y = len - i; y <= len; x++, y++) {if (maxStr.contains(minStr.substring(x, y))) {return minStr.substring(x, y);}}}}return null;}// 如果存在多个长度相同的最大相同子串// 此时先返回String[],后面可以用集合中的ArrayList替换,较方便public String[] getMaxSameSubString1(String str1, String str2) {if (str1 != null && str2 != null) {StringBuffer sBuffer = new StringBuffer();String maxString = (str1.length() > str2.length()) ? str1 : str2;String minString = (str1.length() > str2.length()) ? str2 : str1;int len = minString.length();for (int i = 0; i < len; i++) {for (int x = 0, y = len - i; y <= len; x++, y++) {String subString = minString.substring(x, y);if (maxString.contains(subString)) {sBuffer.append(subString + ",");}}System.out.println(sBuffer);if (sBuffer.length() != 0) {break;}}String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,");return split;}return null;}// 如果存在多个长度相同的最大相同子串:使用ArrayList
//	public List<String> getMaxSameSubString1(String str1, String str2) {
//		if (str1 != null && str2 != null) {
//			List<String> list = new ArrayList<String>();
//			String maxString = (str1.length() > str2.length()) ? str1 : str2;
//			String minString = (str1.length() > str2.length()) ? str2 : str1;
//
//			int len = minString.length();
//			for (int i = 0; i < len; i++) {
//				for (int x = 0, y = len - i; y <= len; x++, y++) {
//					String subString = minString.substring(x, y);
//					if (maxString.contains(subString)) {
//						list.add(subString);
//					}
//				}
//				if (list.size() != 0) {
//					break;
//				}
//			}
//			return list;
//		}
//
//		return null;
//	}@Testpublic void testGetMaxSameSubString() {String str1 = "abcwerthelloyuiodef";String str2 = "cvhellobnmiodef";String[] strs = getMaxSameSubString1(str1, str2);System.out.println(Arrays.toString(strs));}

**题目5:**对字符串中字符进行自然顺序排序。
提示:
1)字符串变成字符数组。
2)对数组排序,选择,冒泡,Arrays.sort();
3)将排序后的数组变成字符串。

	// 第5题@Testpublic void testSort() {String str = "abcwerthelloyuiodef";char[] arr = str.toCharArray();Arrays.sort(arr);String newStr = new String(arr);System.out.println(newStr);}

2. 字符串相关类之可变字符序列:StringBuffer、StringBuilder

因为String对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低,空间消耗也比较高。因此,JDK又在java.lang包提供了可变字符序列StringBuffer和StringBuilder类型。

2.1 StringBuffer与StringBuilder的理解

  • java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。比如:
//情况1:
String s = new String("我喜欢学习"); 
//情况2:
StringBuffer buffer = new StringBuffer("我喜欢学习"); 
buffer.append("数学"); 

请添加图片描述

请添加图片描述

  • 继承结构:
    请添加图片描述
    请添加图片描述
  • StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且提供相关功能的方法也一样。
  • 区分String、StringBuffer、StringBuilder
    • String:不可变的字符序列; 底层使用char[]数组存储(JDK8.0中)
    • StringBuffer:可变的字符序列;线程安全(方法有synchronized修饰),效率低;底层使用char[]数组存储 (JDK8.0中)
    • StringBuilder:可变的字符序列; jdk1.5引入,线程不安全的,效率高;底层使用char[]数组存储(JDK8.0中)

2.2 StringBuilder、StringBuffer的API

StringBuilder、StringBuffer的API是完全一致的,并且很多方法与String相同。

1、常用API

(1)StringBuffer append(xx):提供了很多的append()方法,用于进行字符串追加的方式拼接
(2)StringBuffer delete(int start, int end):删除[start,end)之间字符
(3)StringBuffer deleteCharAt(int index):删除[index]位置字符
(4)StringBuffer replace(int start, int end, String str):替换[start,end)范围的字符序列为str
(5)void setCharAt(int index, char c):替换[index]位置字符
(6)char charAt(int index):查找指定index位置上的字符
(7)StringBuffer insert(int index, xx):在[index]位置插入xx
(8)int length():返回存储的字符数据的长度
(9)StringBuffer reverse():反转

  • 当append和insert时,如果原来value数组长度不够,可扩容。

  • 如上(1)(2)(3)(4)(9)这些方法支持方法链操作。原理:
    请添加图片描述
    2、其它API

(1)int indexOf(String str):在当前字符序列中查询str的第一次出现下标
(2)int indexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询str的第一次出现下标
(3)int lastIndexOf(String str):在当前字符序列中查询str的最后一次出现下标
(4)int lastIndexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询str的最后一次出现下标
(5)String substring(int start):截取当前字符序列[start,最后]
(6)String substring(int start, int end):截取当前字符序列[start,end)
(7)String toString():返回此序列中数据的字符串表示形式
(8)void setLength(int newLength) :设置当前字符序列长度为newLength

@Test
public void test1(){StringBuilder s = new StringBuilder();s.append("hello").append(true).append('a').append(12).append("atbegin");System.out.println(s);System.out.println(s.length());
}@Test
public void test2(){StringBuilder s = new StringBuilder("helloworld");s.insert(5, "java");s.insert(5, "chailinyan");System.out.println(s);
}@Test
public void test3(){StringBuilder s = new StringBuilder("helloworld");s.delete(1, 3);s.deleteCharAt(4);System.out.println(s);
}
@Test
public void test4(){StringBuilder s = new StringBuilder("helloworld");s.reverse();System.out.println(s);
}@Test
public void test5(){StringBuilder s = new StringBuilder("helloworld");s.setCharAt(2, 'a');System.out.println(s);
}@Test
public void test6(){StringBuilder s = new StringBuilder("helloworld");s.setLength(30);System.out.println(s);
}

2.3 效率测试

//初始设置
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");//开始对比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));

2.4 练习

笔试题:程序输出:

String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);System.out.println(sb.length());//System.out.println(sb);//StringBuffer sb1 = new StringBuffer(str);
System.out.println(sb1);//

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

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

相关文章

对数据结构的初步认识

前言: 牛牛开始更新数据结构的知识了.本专栏后续会分享用c语言实现顺序表,链表,二叉树,栈和队列,排序算法等相关知识,欢迎友友们互相学习,可以私信互相讨论哦! &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&a…

Allegro PCB后处理

Allegro PCB后处理&#xff0c;主要是完成线路设计以后&#xff0c;输出生产文件之前的处理。这是看教程做的记录&#xff0c;方便以后自己参考。 教程&#xff1a; [小哥Cadence Allegro 132讲字幕版PCB视频教程]_哔哩哔哩_bilibili 感觉关键是多看右边Options菜单&#xff0…

Simulation Extractable Versions of Groth’s zk-SNARK Revisited学习笔记

1. 引言 等人2020年论文《Simulation Extractable Versions of Groth’s zk-SNARK Revisited》&#xff0c;开源代码实现见&#xff1a; https://github.com/Baghery/ABPR22&#xff08;Rust&#xff0c;基于arkworks开发。使用了Multi-Scalar Multiplication (MSM)技术来优化…

linux下使用ftp下载服务器数据

首先确认服务器地址 比如我要从uniprot获取数据&#xff0c;需要先ping服务器地址&#xff1a; 可见&#xff0c;ftp地址不需要前面的https 匿名登录 匿名&#xff1a;anonymous 密码&#xff1a;任意邮箱&#xff0c;如123163.com 这里的传输模式我使用的是二进制&#xff…

Revit进入Unity教程

一、背景 小伙伴们是否有Revit进入Unity交互的需求呢&#xff1f; 二、实现功能 1.Revit进入Unity,包含模型属性&#xff0c;材质&#xff0c;轻量化等 2.实现BIM构件点选&#xff0c;高亮&#xff0c;属性展示 3.实现BIM模型分层显示&#xff0c;爆炸等效果 学习教程&…

xilinx zynq+vitis实现命令行编译输出xsa以及bin文件

执行菜单命令【开始】—【所有程序】—【Xilinx Design Tools】—【Vivado2020.1】—【Vivado2020.1Tcl Shell】,弹出命令界面 或者cmd命令下输入call D:\soft_install\vivado2020.1\Vivado\2020.1\bin\vivado.bat -mode tcl 2.输入打开工程指令&#xff1a; open_project …

SpringBoot整合Redis,一篇带你入门使用Redis

本文介绍如何将Redis整合到SpringBoot项目中&#xff0c;以及如何配置、封装和使用 文章目录 前言环境搭建项目结构添加依赖 Module封装RedisConfig配置封装常见操作为ServiceRedisServiceRedisLockUtil 测试 前言 参考链接&#xff1a; 英文官网链接中文官网链接Redis githu…

【Matlab】基于紧格式动态线性化的无模型自适应控制

例题来源&#xff1a;侯忠生教授的《无模型自适应控制&#xff1a;理论与应用》&#xff08;2013年科学出版社&#xff09;。 对应书本 4.2 单输入单输出系统(SISO)紧格式动态线性化(CFDL)的无模型自适应控制(MFAC) 例题4.1 题目要求 matlab代码 clc; clear all;%% 期望轨迹…

mybatis-plus的代码生成器的应用

目录 1.工程引入mybatis-plus3-generator代码生成器2.只需要关注mybatis-plus-config.properties然后生成代码3.分别添加依赖解决报错4.加入其它配置然后测试效果 3.4版本 1.工程引入mybatis-plus3-generator代码生成器 mybatis-plus3-generator放入项目工程中&#xff0c;父工…

Java8函数式编程(Lambda表达式,Stream流,Optional)

一.函数式编程思想 面向对象思想主要是关注对象能完成什么事情&#xff0c;函数式编程思想就像函数式&#xff0c;主要是针对数据操作&#xff1b;代码简洁容易理解&#xff0c;方便于并发编程&#xff0c;不需要过分关注线程安全问题 二.lambda表达式 1.概念 lambda表达式…

COMSOL锂离子电池仿真技术与应用

背景&#xff1a; 随着各国燃油车禁售时间表的推出&#xff0c;新能源汽车的地位愈发稳固。而锂离子电池作为电动车的核心动力源&#xff0c;也越来越受到市场的追捧。锂离子电池在制作过程中涉及正极、电解液、负极、隔膜等材料的选取与匹配&#xff0c;极片设计参数的选择等…

如何开发一款用户体验优秀的语音交友app?

在数字时代&#xff0c;人们越来越依赖智能手机上的应用程序来与他人进行交流。其中&#xff0c;语音交友app成为了最受欢迎的应用之一。然而&#xff0c;开发一款成功的语音交友app需要深入了解用户需求与体验。本文将探讨如何开发一款用户体验优秀的语音交友app。 着眼于用户…

[oeasy]python0135_变量名与下划线_dunder_声明与赋值

变量定义 回忆上次内容 变量 就是 能变的量上次研究了 变量标识符的 规则 第一个字符 应该是 字母或下划线合法的标识符可以包括 大小写字母数字下划线 还研究了字符串(str)的函数 isidentifier查询字符串 是否为合法标识符 最后发现 这个isidentifier函数有时候不好使&…

记录bingAI解答pyjwt参数和头部的问题

python jwt.encode()函数的参数是哪些 正在搜索: python jwt.encode()函数的参数 正在为你生成答案… 已收到消息. 在Python中&#xff0c;jwt.encode()函数的参数有三个&#xff1a;第一个是payload&#xff0c;主要用来存放有效的信息&#xff0c;例如用户名&#xff0c;过期…

PCL点云库(1) — 简介与数据类型

目录 1.1 简介 1.2 PCL安装 1.2.1 安装方法 1.2.2 测试程序 1.3 PCL数据类型 1.4 PCL中自定义point类型 1.4.1 增加自定义point的步骤 1.4.2 完整代码 1.1 简介 来源&#xff1a;PCL&#xff08;点云库&#xff09;_百度百科 PCL&#xff08;Point Cloud Library&…

ZLMediaKit流媒体服务器 RTSP推流时候的堆栈

先直接看图 这是ffmpeg向流媒体服务器推流时候的堆栈 引入C 11之后 堆栈会显得特别繁复冗余 看起来 也没有 以前没有C11之前那样 简单明了 太复杂了 标记下 很多函数名字被我改了 因为原来的看起来 同名函数太多了 C11 和lambada 匿名函数 让看堆栈 成了地狱模式 断点断在…

Revit中如何绘制轴线?CAD图纸转轴网操作

一、如何用revit来制作这么一个简单的轴线呢? 01 、新建项目 绘制轴线&#xff0c;首先新建项目建筑样板 02 、轴线快捷键 绘制轴线的快捷键需要牢记&#xff0c;因为经常使用GR 03 、编辑轴线类型 当你画好第一条轴线&#xff0c;需要对轴线类型属性进行调节&#xff0c;一般…

基于tensorflow2.x的多GPU并行训练

由于最近训练transformer&#xff0c;在单卡上显存不够&#xff0c;另外一块卡上也无法加载&#xff0c;故尝试使用双卡并行的策略。将基本的流程、遇见的难题汇总在这里。分布策略解释 使用官方给出的tf.distribute.MirroredStrategy作为分布策略。这个策略通过如下的方式运行…

【架构设计】什么是CAP理论?

1、理论 CAP理论是指计算机分布式系统的三个核心特性&#xff1a;一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区容错性&#xff08;Partition Tolerance&#xff09;。 在CAP理论中&#xff0c;一致性指的是多个节点上的数据…

宝安日报:联诚发跨界创新“追光”十九载!

世界一流声光电智造一体化服务商、国家级高新技术企业、国家级专精特新“小巨人”企业、博士后创新实践基地、深圳自主创新百强企业……这些熠熠生辉的关键词&#xff0c;是位于宝安区航城街道的深圳市联诚发科技股份有限公司&#xff08;以下简称&#xff1a;联诚发&#xff0…