Java常用类之String类
1 - String类的特性
/*
String特性
1 String类:代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作 为此类的实例实现。
2 String是一个final类,代表不可变的字符序列,不可被继承
3 字符串是常量,用双引号("")引起来表示。它们的值在创建之后不能更改。
4 String对象的字符内容是存储在一个字符数组value[]中的
5 String实现了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小
6 String内部定义了final char[] value用于存储字符串数据
7 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
8 字符串常量池中是不会存储相同内容(String.equals())的字符串的。
String的实例化方式:
方式1:通过字面量定义的方式 String s1 = "hello";
方式2:通过new + 构造器的方式 String s2 = new String("world");
*/
两种实例化的区别
2 - String类内存结构说明
public class StringTest { @Test public void test1(){ String s1 = "abc"; // 自面量的定义方式 String s2 = "abc"; System.out.println(s1 == s2); // true // 体现不可变性1:当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值 // 提现不可变性2:当对现有的字符串进行连接操作时,也需要重写指定内存区域赋值,不能使用原有的value进行赋值 // 当调用String的replace()修改指定字符或字符串时,也需要重新指定内存区域 s1 = "hello"; System.out.println(s1); s2 += "def"; System.out.println(s2); String s3 = s1.replace("h","H"); } @Test public void test2(){ // 此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。 String s1 = "javaEE"; String s2 = "javaEE"; // 此时的s3和s4保存的地址值,是数据在堆空间开辟空间以后对应的地址值 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 } }
结论
3 - String类常用方法
/*
int length():返回字符串的长度: return value.length
char charAt(int index): 返回某索引处的字符return value[index]
boolean isEmpty():判断是否是空字符串:return value.length == 0
String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
String trim():返回字符串的副本,忽略前导空白和尾部空白
boolean equals(Object obj):比较字符串的内容是否相同
boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大 小写
String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
int compareTo(String anotherString):比较两个字符串的大小
String substring(int beginIndex):返回一个新的字符串,它是此字符串的从 beginIndex开始截取到最后的一个子字符串。
String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字 符串从beginIndex开始截取到endIndex(不包含)的一个子字符串
boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的 子字符串是否以指定前缀开始
boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列 时,返回 true
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出 现处的索引,从指定的索引开始
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后 一次出现处的索引,从指定的索引开始反向搜索 注:indexOf和lastIndexOf方法如果未找到都是返回-1
替换
String replace(char oldChar, char newChar):返回一个新的字符串,它是 通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使 用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement) : 使用给 定 的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement) : 使用给 定 的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
匹配
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
切片
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此 字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中
*/
public class StringMethodTest { @Test public void test1(){ // int length():返回字符串的长度: return value.length String str = "hello"; int strLength = str.length(); System.out.println(strLength); // 5 // char charAt(int index): 返回某索引处的字符return value[index] System.out.println(str.charAt(0)); // h System.out.println(str.charAt(4)); // o // boolean isEmpty():判断是否是空字符串:return value.length == 0 System.out.println(str.isEmpty()); // false // String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写 str = "HELLO"; String s1 = str.toLowerCase(); System.out.println(s1); // hello // String trim():返回字符串的副本,忽略前导空白和尾部空白 String s2 = " hello world "; String s3 = s2.trim(); System.out.println("--"+s2+"--"); // -- hello world -- System.out.println("--"+s3+"--"); // --hello world-- } @Test public void test2(){ // boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大 小写 String s1 = "HelloWorld"; String s2 = "helloworld"; System.out.println(s1.equals(s2)); // false System.out.println(s1.equalsIgnoreCase(s2)); // true // String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+” String s3 = "hello"; String s4 = " world"; System.out.println(s3.concat(s4)); // hello world // int compareTo(String anotherString):比较两个字符串的大小 从结果正负进行比较 System.out.println(s3.compareTo(s4)); // 72 说明 s3 > s4 // String substring(int beginIndex):返回一个新的字符串,它是此字符串的从 beginIndex开始截取到最后的一个子字符串。 String s5 = "李白打野,韩信偷家"; System.out.println(s5); System.out.println(s5.substring(5)); // 韩信偷家 System.out.println(s5.substring(0,4)); // 李白打野 } }
4 - String与基本数据类型转换
package com.lzh.java1; import org.junit.Test; /* String类与其他结构之间的转换 */ public class StringTest2 { // String --> 基本数据类型、包装类 @Test public void test1(){ String s1 = "123"; // String --> 基本数据类型、包装类:调用包装类的静态方法:parseXxx() int number = Integer.parseInt(s1); System.out.println(number); // 123 // 基本数据类型、包装类 --> String:调用String类的valueof() int num = 1222; String s2 = String.valueOf(num); System.out.println(s2.getClass()); System.out.println(s2); } }
4 - String与char[](字符)数组转换
// String与char[]数组之间的转换 @Test public void test1(){ String s1 = "abc123"; char[] charArray = s1.toCharArray(); // String类 --> char[] :调用String.toCharArray(); System.out.println(charArray); // char[] --> String :调用String特殊 构造器 char[] arr = new char[]{'h','e','l','l','o'}; String s2 = new String(arr); System.out.println(s2.getClass()); // class java.lang.String System.out.println(s2); // hello }
5 - String与byte[](字节)数组转换
// String与byte[]数组之间的转换 @Test public void test2() throws UnsupportedEncodingException { String s1 = "123abc"; // String --> byte[] :调用String.getBytes() byte[] byteArray = s1.getBytes(); // 使用默认字符集,进行转换 System.out.println(byteArray.getClass()); System.out.println(Arrays.toString(byteArray)); // byte[] --> String :调用构造器字符集解码指定的 byte 数组 String s2 = new String(byteArray,"utf-8"); // 指定字符集utf-8 进行解码 System.out.println(s2.getClass()); // class java.lang.String System.out.println(s2); // 123abc
6 - String类常见算法
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; /* * 1.模拟一个trim方法,去除字符串两端的空格。 * * 2.将一个字符串进行反转。将字符串中指定部分进行反转。比如将“abcdefg”反转为”abfedcg” * * 3.获取一个字符串在另一个字符串中出现的次数。 比如:获取“ab”在 “cdabkkcadkabkebfkabkskab” 中出现的次数 4.获取两个字符串中最大相同子串。比如: str1 = "abcwerthelloyuiodef“;str2 = "cvhellobnm"//10 提示:将短的那个串进行长度依次递减的子串与较长 的串比较。 5.对字符串中字符进行自然顺序排序。"abcwerthelloyuiodef" 提示: 1)字符串变成字符数组。 2)对数组排序,选择,冒泡,Arrays.sort(str.toCharArray()); 3)将排序后的数组变成字符串。 */ public class StringExer { // 第1题 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; } // 第2题 // 方式一: public String reverse1(String str, int start, int end) {// start:2,end:5 if (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(); } @Test public void testReverse() { String str = "abcdefg"; String str1 = reverse3(str, 2, 5); System.out.println(str1);// abfedcg } // 第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; } } @Test public void testGetCount() { String str1 = "cdabkkcadkabkebfkabkskab"; String str2 = "ab"; int count = getCount(str1, str2); System.out.println(count); } @Test public void testMyTrim() { String str = " a "; // str = " "; String newStr = myTrim(str); System.out.println("---" + newStr + "---"); } // 第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; // } @Test public void testGetMaxSameSubString() { String str1 = "abcwerthelloyuiodef"; String str2 = "cvhellobnmiodef"; String[] strs = getMaxSameSubString1(str1, str2); System.out.println(Arrays.toString(strs)); } // 第5题 @Test public void testSort() { String str = "abcwerthelloyuiodef"; char[] arr = str.toCharArray(); Arrays.sort(arr); String newStr = new String(arr); System.out.println(newStr); } }
7-String类、StringBuffer类、StringBuilder类
package com.lzh.java2; import org.junit.Test; /* StringBuffer和StringBuilder的使用: String、StringBuffer、StringBuilder三者的异同? 同:底层都使用char[]存储 String:不可变的字符序列 StringBuffer:可变的字符序列 --> 线程安全;效率偏低 StringBuilder(JDK5.0新增):可变的字符序列 --> 线程不安全;效率偏高 效率从高到低:StringBuilder > StringBuffer > String 源码分析: String s1 = new String(); // char value = new char[0]; String s2 = new String("abc"); // char value = new char[]{'a','b','c'}; StringBuffer s3 = new StringBuffer(); // char value = new char[16]; 底层创建了一个长度是16的数组。 s3.append('a'); // value[0] = 'a'; s3.append('b'); // value[1] = 'b'; StringBuffer s4 = new StringBuffer("abc"); // char[] value = new char["abc".length+16]; 问题1:System.out.println(s4.length); // 3 问题2:扩容问题:如果要添加的数据在底层数组中装不下了,那就需要扩容底层的数组,默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。 */ public class StringBufferTest { /* StringBuffer类常用的方法: StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接 StringBuffer delete(int start,int end):删除指定位置的内容 StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str StringBuffer insert(int offset, xxx):在指定位置插入xxx StringBuffer reverse() :把当前字符序列逆转 public int indexOf(String str) :返回指定字符串的索引 public String substring(int start,int end) :返回一个从Start开始 到end索引结束的左闭右开区间的子字符串 public int length() public char charAt(int n ) public void setCharAt(int n ,char ch) */ @Test public void test1(){ StringBuffer s1 = new StringBuffer("he"); s1.append("llo"); s1.append(" world"); System.out.println(s1); // hello world StringBuffer s2 = s1.delete(6,11); System.out.println(s1); // hello System.out.println(s2); // hello } } /* 总结: 增:append() 删:delete() 改:setCharAt()/replace() 查:charAt() 插:insert() 长度:length() 遍历:for循环 */
注:三者之间的转换都是用构造器