第十七天:String类
加油,奥里给~!
狂神未更新,转千锋教育 (bilibili.com)
学习内容
String
字符串是常量,创建之后不可改变
Java对字符串进行了保护,不能直接修改这块内存中字符串的值。我们要修改的话将会创建一块新的空间。
字符串字面值储存在字符串池中,可以共享
在JDK6.0及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中; 在JDK7.0版本,字符串常量池被移到了堆中了。至于为什么移到堆内,大概是由于方法区的内存空间太小了
1 2 3 4 5 6 7 8 package com.joker_yue.javalearn.string;public class Demo01 { public static void main (String[] args) { String name = "hello" ; name = "张三" ; } }
注意看,我们首先创建了 一个String类对象name,然后初始化为"hello",其在字符串池中开辟了一个空间,内容为“hello”。后面我们将其修改为“张三”,将会重新开辟一个空间,内容为“张三“,然后将name的引用指向这块新空间。
但是如果我们再创建一个String类对象name2,将其初始化为”张三“,那么name和name2是否是同一个地址呢。答案是肯定的。因为Java在创建字符串变量时,会先在字符串池中搜索有无相同者。如果有,就将其赋值给这个对象。
两种赋值方式:
1 2 String s = new String("Hello"); //产生两个对象,堆、池中各储存一个 //其实在堆中的对象没有值,而是指向了常量池的地址
问题又来了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.joker_yue.javalearn.string;public class Demo01 { public static void main (String[] args) { String name = "hello" ; name = "张三" ; String str = new String ( "Java才是世界上最好的语言" ); String str2 = new String ("Java才是世界上最好的语言" ); System.out.println(str==str2); } }
答案是输出false
。虽然两者在字符串池中是同一块空间,但是栈中的对象会先指向堆中的空间,堆再指向字符串池。在这里,两者的堆的空间地址不同,所以自然是输出false
所以我们想让它们比较值而不是比较地址,就使用String.equals()方法
常用方法
public int length(); 返回字符串的长度
public char charAt(int index); 根据下标获取字符
public boolean contains(String str); 判断当前字符串中是否包含str
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String contain = "Java是世界上最好的编程语言" ; System.out.println(contain.length()); System.out.println(contain.charAt(0 )); System.out.println(contain.contains("Java" )); System.out.println(contain.contains("PHP" )); } }
输出结果为
public char[] toCharArray(); 将字符串转换为数组
public int indexOf(String str); 查找str首次出现的下标。若存在,则返回该下标;否则返回-1
public int lastIndexOf(String str); 查找字符串在当前字符串最后一次出现的下标索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.joker_yue.javalearn.string;import java.util.Arrays;public class Demo02 { public static void main (String[] args) { String contain = "Java是世界上最好的编程语言,Java真香,Java真棒" ; System.out.println(Arrays.toString(contain.toCharArray())); System.out.println(contain.indexOf("Java" )); System.out.println(contain.indexOf("Java" ,9 )); System.out.println(contain.lastIndexOf("Java" )); } }
最后的输出结果为
1 2 3 4 [J, a, v, a, 是, 世, 界, 上, 最, 好, 的, 编, 程, 语, 言, ,, J, a, v, a, 真, 香, ,, J, a, v, a, 真, 棒] 0 16 23
public String trim(); 去掉字符串前后的空格(不包括中间的)
public String toUpperCase(); 将小写转换为大写
public boolean endWith(String str); 判断字符串是否以str结尾
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.joker_yue.javalearn.string;import java.util.Arrays;import java.util.Locale;public class Demo02 { public static void main (String[] args) { String contain = "Hello World " ; System.out.println(contain.trim()); System.out.println(contain.toUpperCase()); System.out.println(contain.toLowerCase()); String filename= "hello.java" ; System.out.println(filename.endsWith("java" )); System.out.println(filename.startsWith("hello" )); } }
输出结果为
1 2 3 4 5 Hello World HELLO WORLD hello world true true
public String replace (char oldChar,char newChar); 将旧字符串替换为新字符串
public String[] split(String str); 根据str做拆分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String contain = new String ("Hello.java" ); System.out.println(contain.replace("java" , "php" )); String say = "java is the best programming language" ; String[] arr = say.split(" " ); System.out.println(arr.length); for (String index : arr) { System.out.println(index); } } }
最后的输出结果是:
1 2 3 4 5 6 7 8 Hello.php 6 java is the best programming language
emm,我们将say的内容修改为:“java is the best programming language,java newbee”,再次输出,会得到如下结果:
1 2 3 4 5 6 7 8 9 Hello.php 7 java is the best programming language,java newbee
我们会发现language和newbee写在一起了,我们想让其做","切割,怎么办呢
我们这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String contain = new String ("Hello.java" ); System.out.println(contain.replace("java" , "php" )); String say = "java is the best programming language,java newbee" ; String[] arr = say.split("[ ,]" ); System.out.println(arr.length); for (String index : arr) { System.out.println(index); } } }
然后我们就可以发现能够输出如下结果:
1 2 3 4 5 6 7 8 9 10 Hello.php 8 java is the best programming language java newbee
但是这时候我们再将say更改下:“java is the best programming language,java newbee”
我们会发现,它将会输出如下结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 Hello.php 11 java is the best programming language java newbee
是的,它将空格也算入在内了!
于是我们可以这么改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String contain = new String ("Hello.java" ); System.out.println(contain.replace("java" , "php" )); String say = "java is the best programming language,java newbee" ; String[] arr = say.split("[ ,]+" ); System.out.println(arr.length); for (String index : arr) { System.out.println(index); } } }
于是会输出如下结果:
1 2 3 4 5 6 7 8 9 10 Hello.php 8 java is the best programming language java newbee
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String s1= "hello" ; String s2="Hello" ; System.out.println(s1.equals(s2)); } }
上述代码会输出false
,因为s1全部为小写,而s2有大写。我们想要忽视大小写进行比较,可以使用equalsIgnoreCase()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String s1= "hello" ; String s2="Hello" ; System.out.println(s1.equalsIgnoreCase(s2)); } }
上述代码的运行结果为true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String s1= "hello" ; String s2="Hello" ; System.out.println(s1.equalsIgnoreCase(s2)); String s3 = "abc" ; String s4 = "xyz" ; System.out.println(s3.compareTo(s4)); } }
上述代码的输出结果为
但是如果比较的两个字符串有一个是另一个的前半段,而且他们两个长度不相同,将会返回长度的差值,而不是第一个不同的字符的差值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.joker_yue.javalearn.string;public class Demo02 { public static void main (String[] args) { String s1= "hello" ; String s2="Hello" ; System.out.println(s1.equalsIgnoreCase(s2)); String s3 = "abc" ; String s4 = "xyz" ; System.out.println(s3.compareTo(s4)); String s5 = "abc" ; String s6 = "abcxyz" ; System.out.println(s5.compareTo(s6)); } }
上述代码运行将会输出
String 案例
需求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.joker_yue.javalearn.string;public class StringDemoTest { public static void main (String[] args) { String str = "this is a text" ; String[] arr = str.split(" " ); System.out.println("将str中的单词获取出来" ); for (String s: arr){ System.out.println(s); } System.out.println("将str中的text替换为practice" ); String s2 = str.replace("text" ,"practice" ); System.out.println("s2" ); System.out.println("在text前面加上easy" ); String s3 = str.replace("text" ,"easy text" ); System.out.println(s3); System.out.println("将所有的单词的首字母变成大写" ); for (int i = 0 ;i<arr.length;i++){ char first = arr[i].charAt(0 ); char upperFirst = Character.toUpperCase(first); String newStr = upperFirst+arr[i].substring(1 ); System.out.println(newStr); } } }
可变字符串
StringBuffer:可变长度的字符串,JDK1.0提供,运行效率慢、线程安全
事先开辟好空间(缓冲区)。在进行操作的时候直接操作缓冲区
StringBiulder:可变长度的字符串,JDK5.0提供,运行效率快、线程不安全
多线程没有StringBuffer安全。但是在单线程的时候比StringBuffer快
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package com.joker_yue.javalearn.string;public class StringBuilderBuffer { public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("Java世界第一" ); System.out.println(sb); sb.append("Java香" ); System.out.println(sb); sb.append("Java真不错" ); System.out.println(sb); sb.insert(0 ,"我在最前面" ); System.out.println(sb); sb.replace(0 ,5 ,"Hello World " ); System.out.println(sb); sb.delete(0 ,12 ); System.out.println(sb); } }
我们接下来比较String、StringBuffer的速度快慢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.joker_yue.javalearn.string;public class StringBuilderBuffer { public static void main (String[] args) { long start = System.currentTimeMillis(); String string = "" ; for (int i = 0 ;i<99999 ;i++){ string+=i; } System.out.println(string); long end = System.currentTimeMillis(); System.out.println("用时:" +(end-start)); } }
最后输出结果为
我们再看看StringBuilder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.joker_yue.javalearn.string;public class StringBuilderBuffer { public static void main (String[] args) { long start = System.currentTimeMillis(); StringBuilder string = new StringBuilder (); for (int i = 0 ;i<99999 ;i++){ string.append(i); } System.out.println(string); long end = System.currentTimeMillis(); System.out.println("用时:" +(end-start)); } }
最后输出:
所以我们看到StringBuilder非常快!