Java学习之==>常用字符串方法
1、定义字符串
1 // 定义, 为初始化 2 String str1; 3 4 // 定义, 并初始化为null 5 String str2 = null; 6 7 // 定义, 并初始化为空串 8 String str3 = ""; 9 10 // new 空串 11 String str4 = new String(); 12 13 // new "hello" 14 String str5 = new String("hello"); 15 16 // char数组创建 17 char[] chars = {'h', 'e', 'l', 'l', 'o'}; 18 String str6 = new String(chars); 19 System.out.println("str6=" + str6); 20 21 // 在char数组中切片,从0开始,切3个长度,即:hel 22 String str7 = new String(chars, 2, 3); 23 System.out.println("str7=" + str7); 24 25 // ASCII码组成的数组切片后再转化成字符串 26 int[] codePoints = new int[]{97, 98, 99, 100, 101}; 27 String str8 = new String(codePoints, 0, 3); 28 System.out.println("str8=" + str8); 29 30 // 将字符串转化为字节数组 31 String val = "中国"; 32 String str9 = new String(val.getBytes()); 33 System.out.println("str9 = " + str9); 34 35 // 将字符串转化为字节数组并指定字符编码 36 String str10 = new String(val.getBytes("UTF-8"), StandardCharsets.UTF_8); 37 System.out.println("str10 = " + str10);
2、获取字符串的属性
1 String str = " "; 2 3 // String str = ""; // 空串 4 // String str = null; // 空指针 5 // 字符串是否为空,"",若为空则返回true,若不为空则返回false 6 boolean isEmpty = str.isEmpty(); 7 System.out.println("str.isEmpty() = " + isEmpty); 8 9 // 业务中经常使用的判断操作,是不是空指针, 然后才是判断是不是空串 10 // checkpoint 检查点, 这里是一些说明 11 if (str == null || str.isEmpty()) { 12 System.out.println("这是一个空串/空指针"); 13 } 14 15 // 字符串的长度 16 int length = str.length(); 17 System.out.println("length = " + length); 18 19 // 获取字符串的hash码 20 int hashCode = str.hashCode(); 21 System.out.println("hashCode = " + hashCode);
3、转化:将各种数据类型转化为字符串
1 // 定义字符串 2 String str = "hello world"; 3 4 // int & Integer 转 String 5 Integer num1 = 1024; 6 int num2 = num1; 7 String intValue = String.valueOf(num2); 8 System.out.println(intValue); 9 10 // long & Long 转String的操作 11 Long num3 = 5689087678L; 12 long num4 = num3; 13 String longValue = String.valueOf(num4); 14 System.out.println(longValue); 15 16 // float(Float) & double(Double) 转String, 17 String.valueOf(10.24F); 18 String.valueOf(10.24D); 19 20 // boolean类型转化成String 21 String.valueOf(false); 22 23 // 字节转化为String 24 String.valueOf('a'); 25 26 // 对象转化成String 27 String.valueOf(new byte[]{1, 2, 3, 4}); 28 String.valueOf(new char[]{'a', 'b', 'c', 'd'});
4、分割与连接
1 String str = "hello,world,hi,thank,you"; 2 // 分割 3 String[] strarray = str.split(","); 4 5 // 数组遍历 6 for (String s : strarray) { 7 System.out.println(s); 8 } 9 10 System.out.println("\n-----我是分割线------\n"); 11 12 String[] strarray2 = str.split(",", 3); 13 for (String s : strarray2) { 14 System.out.println(s); 15 } 16 17 System.out.println("\n-----我是分割线------\n"); 18 19 // 连接 20 String joinResult1 = String.join("+", strarray); 21 System.out.println("joinResult1 = " + joinResult1);
5、截取
1 String str = "123456789"; 2 3 // 从beginIndex开始截取,一直截取到最后 4 String res1 = str.substring(3); 5 System.out.println("res1 = " + res1); 6 7 System.out.println("\n-----我是分割线------\n"); 8 9 // 从beginIndex开始截取一直截取到endIndex 10 String res2 = str.substring(3, 6); 11 System.out.println("res2 = " + res2); 12 13 System.out.println("\n-----我是分割线------\n"); 14 15 String originStr = " \nabcdefg\n "; 16 System.out.println("origin:[" + originStr + "]"); 17 18 // 去掉字符串两边的空格和换行符 19 originStr = originStr.trim(); 20 System.out.println("origin:[" + originStr + "]");
6、定位
1 String str = "hello,love,how are you, love,thanks,"; 2 3 // 从前向后查找 4 int index = str.indexOf("love"); 5 System.out.println("love first index = " + index); 6 7 index = str.indexOf("love", 7); 8 System.out.println("love jump index = " + index); 9 10 // 循环定位所有的字符串 11 String[] strarray = str.split(","); 12 for (String s : strarray) { 13 int i = str.indexOf(s); 14 System.out.println(s + ":" + i); 15 } 16 17 index = str.indexOf('e'); 18 System.out.println("char index = " + index); 19 20 // 从后向前查找 21 index = str.lastIndexOf("love"); 22 System.out.println("last index = " + index); 23 24 // 找不着,返回-1 25 index = str.indexOf("yes"); 26 System.out.println("none exists index = " + index); 27 28 // 根据下标返回字符 29 char ch = str.charAt(0); 30 System.out.println("ch = " + ch); 31 ch = str.charAt(1); 32 System.out.println("ch = " + ch);
7、判断:值相等,地址相等,前缀相等,后缀相等,包含
String str1 = "hello"; String str2 = "hi"; String str3 = "hello"; String str4 = "HELLO"; // 判断字符串的值是否相等,不相等,返回false,相等则返回的true boolean isEq = str1.equals(str2); System.out.println("1:" + isEq); isEq = str1.equals(str3); System.out.println("2:" + isEq); // 判断内存地址是否相等 isEq = (str1 == str3); System.out.println("3:" + isEq); System.out.println(System.identityHashCode(str1)); System.out.println(System.identityHashCode(str3)); // 忽略大小写的 相等判断 isEq = str1.equalsIgnoreCase(str4); System.out.println("4:" + isEq); isEq = str1.equals(str4); System.out.println("5:" + isEq); // 起始前缀匹配判断 ,210_ 支付宝,230_ 微信, String orderId1 = "210_100012342324324"; String orderId2 = "230_100012342324324"; boolean isStartWith1 = orderId1.startsWith("210_"); boolean isStartWith2 = orderId2.startsWith("210_"); System.out.println("isStartWith:" + isStartWith1); System.out.println("isStartWith:" + isStartWith2); // 末尾后缀匹配判断 final boolean isEndWith = orderId1.endsWith("4324"); System.out.println("isEndWith = " + isEndWith); // 包含判断,如果包含子串返回true, 不包含返回false String str = "hello world,hi"; final boolean isContains = str.contains("hi"); System.out.println("isContains = " + isContains);
8、转换&&替换
// 将所有字符转换为大写 String str = "hello"; String upperCase = str.toUpperCase(); System.out.println("upperCase = " + upperCase); // 将所有字符转换为小写 String str2 = "HELLO"; final String lowerCase = str2.toLowerCase(); System.out.println("lowerCase = " + lowerCase); // 将字符串转换为字符数组 String str3 = "abcde"; char[] chars = str3.toCharArray(); for (char ch : chars) { System.out.println(ch); } // 替换目标字符串 "hello world".replace("hello", "hi"); "hello world,hello java".replaceAll("hello", "hi"); "hello world,hello java".replaceFirst("hello", "hi");
9、面试点
1、String str = new String(“Hello”) 这段代码创建了几个对象 两个,字符串“Hello”存在常量池中,由这个字符串创建的一个新对象(存在堆内存当中)赋给了str 2、 public void interviewPoint1() { String str1 = "hello"; String str2 = new String("hello"); System.out.println(str1 == str2); // false System.out.println(str1.equals(str2)); // true } 3、 public void interviewPoint2() { String str1 = "hello"; String str2 = "hello"; System.out.println(str1 == str2); // true System.out.println(str1.equals(str2)); // true } 4、 public void interviewPoint3() { String str1 = "a" + "b" + "c"; String str2 = "abc"; System.out.println(str1 == str2); // true System.out.println(str1.equals(str2)); // true } 5、 public void interviewPoint4() { String str1 = "ab"; String str2 = "abc"; String str3 = str1 + "c"; System.out.println(str2 == str3); // false System.out.println(str2.equals(str3)); // true }
10、谈谈String, StringBuilder, StringBuffer的区别
设计
- String
-
- 由于其实现是不可变的(Immutable),进而原生支持线程安全,因为String对象一但建立就不可在修改。
- 引申: java8的 LocalDateTime。
- StringBuilder和StringBuffer
-
- 均继承自AbstractStringBuilder。
- 实现方法除Buffer的所有方法使用了synchronized外,无其他区别。
- 内部使用char数组做数据接收。
- class AbstractStringBuilder # char[] value;
- 默认大小是16,若超过16之后,会触发数组的扩容,arrayCopy,会有性能开销。
- 因此若能预估大小,尽量做到设定预期值,避免扩容。
应用
- String
-
- Java中字符串类,被修饰为final,因此是不可变数值的类,也不可被继承。
- 进而其相关操作,如截取,剪切,拼接等都是产生新的String。
- StringBuffer
- 当大量的String进行拼接时会产生大量的对象,为解决此问题则引入了StringBuffer。
- StringBuffer本质是一个线程安全的可修改的字符序列,为保证其线程的安全必定会损失一定的性能开销。
- 所有方法都带有 synchronized 关键字修饰 ** StringBuilder。
- jdk1.5新增,功能与StringBuffer一致,只是去掉了线程安全的实现部分,进而可提升其性能。
扩展
即使尽量减少了拼接带来的大量字符串对象的产生,但是程序内依旧还有很多重复的字符串,要怎么解决呢? 使用**缓存机制 **
- intern()方法,告知jvm将字符串缓存起来共用。
- dk1.6时不建议使用此方法,因为这个缓存的动作将将对象存储在PermGen(永久代),其空间有限,很难被gc,弄不好就容易造成OOM。
- 1.6之后的版本将此缓存至于堆中,大小为60013。
- 查看数值的参数配置: -XX:+PrintStringTableStatistics。
- 配置缓存的大小: -XX:StringTableSize=1024。
- 缺点: 程序员自己手动显示调用,很难把控好。
- jdk1.8 8u20之后,增加了一个新特性,G1 GC字符串排重。
- 将相同数据的字符串指向同一份数据来做到的,JVM底层提供支持。
- 此功能默认关闭,开启: -XX:UseStringDuplication, 前提: 使用G1 GC。