Java——String类全面解析

云平台

  目录 2.1、==比较是否变量中的值 2.2、boolean equal(Object anObject)方法,按照字典序(字符大小顺序)比较 2.4、compareToIgnoreCase方法:忽略大小写比较 4.1、数值和字符串转化 5.5、contains是否包含某内容 8、StringBuilder和StringBuffffer 总结StringBuilder与String类的区别 题目一:字符串中的第一个唯一字符 题目二:字符串最后一个单词的长度 题目三:检测字符串是否为回文 String类,在Java中属于字符串类型。 1、字符串构造 常用的三种构造字符串的方式: 代码: public class Test { public static void main(String[] args) { //方法一: String str1="happy";//str是一个引用变量,happy属于字符串常量 System.out.println(str1); //方法二: String str2=new String("lyj"); System.out.println(str2); //方法三 char[] ch={'l','o','n','g'};//字符数组 String str3=new String(ch); System.out.println(str3); }}运行结果: 补充: String是引用类型,内部并不存储字符串本身 查看String类,会看到他有两个属性 比如我们看例中的happy的内存分布: 2、String对象的比较 2.1、==比较是否变量中的值 例: public class Test { public static void main(String[] args) { int a=10; int b=30; int c=10; System.out.println(a==b); System.out.println(a==c); }}运行结果如下: 但是这个比较只针对内置类型,对于引用类型,这么比较就是错误的,因为他比较的是值,也就是比较的是引用中的地址,并没有比较其指向的内容 2.2、boolean equal(Object anObject)方法,按照字典序(字符大小顺序)比较 String类重写了父类Object中的Equals方法,Object中equals默认是==比较,源码: 而String重写,源码: 按照以下规则比较: 例: public class Test { public static void main(String[] args) { String str1="lyj"; String str2="lya"; String str3="lyj"; System.out.println(str1.equals(str2)); System.out.println(str1.equals(str3)); }}运行: 2.3、compareTo方法: 查看String中compareTo方法源码: 例: public static void main(String[] args) { String str1="lyj"; String str2="lya"; String str3="lyj"; int ret1=str1.compareTo(str2); if(ret1>0) { System.out.println("str1>str2"); } else if(ret1==0) { System.out.println("str1=str2"); } else { System.out.println("str1<str2"); } int ret2=str1.compareTo(str3); if(ret2>0) { System.out.println("str1>str3"); } else if(ret2==0) { System.out.println("str1=str3"); } else { System.out.println("str1<str3"); } }运行结果: 2.4、compareToIgnoreCase方法:忽略大小写比较 例: public static void main(String[] args) { String str1="lyj"; String str2="LYJ"; System.out.println(str1.equalsIgnoreCase(str2)); }运行结果: 3、字符串查找 常用的方法总结: 方法 功能 char charAt(int index) 放回index位置上字符,如果index为负数或者越界,抛出indexOutOfBoundsException异常 int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1 int intdexOf(int ch,int fromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有返回-1 int indexOf(String str) 返回dtr第一次出现的位置,没有返回-1 int indexOf(String str,int fromIndex) 从fromIndex位置开始找str第一次出现的位置,没有返回-1 int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1 int lastIndexOf(int ch,int 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1 int lastIndexOf(String str) 从后往前找,返回 str 第一次出现的位置,没有返回 -1 int lastIndexOf(String str, int fromIndex) 从 fromIndex 位置开始找,从后往前找 str 第一次出现的位置,没有返 回 -1 范例: public static void main(String[] args) { String str="abcdcf"; for (int i = 0; i < str.length(); i++) { char ch=str.charAt(i); System.out.print(ch+" ");//a b c d e f } System.out.println(); System.out.println(str.indexOf('d'));//3 System.out.println(str.indexOf('c',3));//4 String str1="abclyjdcef"; System.out.println(str1.indexOf("lyj"));//3 System.out.println(str1.indexOf("lyj",4));//-1 System.out.println(str1.lastIndexOf('c'));//7 System.out.println(str1.lastIndexOf('c',4));//2 System.out.println(str1.lastIndexOf("lyj"));//3 System.out.println(str1.lastIndexOf("lyj",6));//3 }4、转化 4.1、数值和字符串转化 public static void main(String[] args) { //其他类型转换为字符串 String str1=String.valueOf(410); String str2=String.valueOf('l'); String str3=String.valueOf(3.14); String str4=String.valueOf(3.5f); String str5=String.valueOf(false); String str6=String.valueOf(new Person("jingjing",18)); System.out.println(str1+" "+str2+" "+str3+" "+str4+" "+str5+" "+str6);//410 l 3.14 3.5 false Person{name='jingjing', age=18} //字符串转换为其他类型 int val=Integer.valueOf("410"); int val1=Integer.parseInt("318"); double val2=Double.parseDouble("3.14"); float val3=Float.parseFloat("3.5f"); System.out.println(val+" "+val1+" "+val2+" "+val3);//410 318 3.14 3.5 }4.2、大小写转换 public static void main(String[] args) { String str1="family"; System.out.println(str1.toUpperCase());//FAMILY String str2="LOVE"; System.out.println(str2.toLowerCase());//love }4.3、字符串转数组 public static void main(String[] args) { //字符串转数组 String str1="today is so..."; char[] chars=str1.toCharArray(); for (int i = 0; i < str1.length(); i++) { System.out.print(chars[i]+" ");//t o d a y i s s o . . . } //数组转字符串 String str2=new String(chars); System.out.println(str2);//today is so... }4.4、格式化 public static void main(String[] args) { String s = String.format("%d-%d-%d", 2022, 8,12); //有点类似于printf System.out.println(s);//2022-8-12 }5、常用方法 5.1、字符串替换 方法 功能 String replace(char oldChar,char newChar) 替换指定字符 String replace(String target,String replacement) 替换指定内容 String replaceAll(String regex, String replacement) 替换所有的指定内容 String replaceFirst(String regex, String replacement) 替换收个内容 范例: public static void main(String[] args) { String str1="ablyjlyjablyjabcdef"; String ret=str1.replace('l','k'); System.out.println(ret);//abkyjkyjabkyjabcdef ret=str1.replace("lyj","cyk"); System.out.println(ret);//abcykcykabcykabcdef ret=ret.replaceFirst("cyk","lyj"); System.out.println(ret);//ablyjcykabcykabcdef ret=ret.replaceAll("cyk","lyj"); System.out.println(ret);//ablyjlyjablyjabcdef }5.2、字符串拆分 方法 功能 String[] split(String regex) 将字符串全部拆分 String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组 public static void main(String[] args) { String str="lyjhhh@ccykee"; String[] ret=str.split("@"); System.out.println(Arrays.toString(ret));//[lyjhhh, ccykee] str="lyj@cyk&lyz@lxm"; ret=str.split("@",2); System.out.println(Arrays.toString(ret));//[lyj, cyk@lyz@lxm] }注: 如果一个字符串中有多个分隔符,可以用 " " 作为连字符 . public static void main(String[] args) { String str="lyz&cyk*lyj@lxm"; String[] ret=str.split("& @"); System.out.println(Arrays.toString(ret));//[lyz, cyk*lyj, lxm] }5.3、字符串截取 方法 功能 String substring(int beginIndex) 从指定索引截取到结尾 String substring(int beginIndex, int Index) 截取部分内容 范例: public static void main(String[] args) { String str="helloworld"; String ret1=str.substring(1); System.out.println(ret1);//elloworld String ret2=str.substring(1,5);//前开后闭 System.out.println(ret2);//ello }5.4、trim空格字符处理 String trim() 功能: 去掉字符串中的左右空格 , 保留中间空格 范例: public static void main(String[] args) { String str=" hello world "; String ret=str.trim(); System.out.println(ret);//hello world }5.5、contains是否包含某内容 判断是否包含某字符串 public static void main(String[] args) { String str="hellolyjhahaha"; System.out.println(str.contains("lyj"));//true }6、字符串常量池 字符串常量池,其底层是一个StringTable的哈希表 通俗的来说,就是为了使程序运行得更快,更加节省内存,Java就引出了,池的概念,而字符串常量池,就是存放一些我们常用的字符串,其由双引号括起来的,例: String str =" lyj ";其内存布局: 注:上述提到过的,String类有两个属性,一个value,一个hash 在字符串常量池中,没有对应的字符串时,将其存入,如果有了,则就会使用那一份现有的数据。 根据上述提示,分析下面的代码运行结果: public static void main(String[] args) { String str1="lyj"; String str2="lyj"; String str3=new String("lyj"); String str4=new String("lyj"); System.out.println(str1==str2);//true System.out.println(str3==str4);//false System.out.println(str1==str3);//false }内存布局分析: 补充: intern方法 该方法的作用是手 动将创建的 String 对象添加到常量池中 。 public static void main(String[] args) { char[] ch=new char[]{'l','y','j'}; String s1=new String(ch);//没有入池 s1.intern();//入池 String s2="lyj"; System.out.println(s1==s2);//true char[] ch1=new char[]{'a','b','c'}; String s3=new String(ch1); String s4="abc"; System.out.println(s3==s4);//false }面试题: 请解释String类中两种对象实例化的区别(常量池中都不存在以下字符串) JDK1.8中 提示:根据上述例中的内存图,可知,每创建一个字符串对象时,有一个value和一个hash, value 又指 向对应的字符串,一共两个对象 1. String str = "hello" 正解:2 只会开辟一块堆内存空间,保存在字符串常量池中,然后str共享常量池中的String对象 2. String str = new String("hello") 正解:3 会开辟两块堆内存空间,字符串"hello"保存在字符串常量池中,然后用常量池中的String对象 给新开辟 的String对象赋值。 3. String str = new String(new char[]{'h', 'e', 'l', 'l', 'o'}) 正解:3 现在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内 容拷贝到 String对象中 7、字符串的不可变性 String类不可变的原因: 1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了. 2. 不可变对象是线程安全的. 3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中. 从哪儿观察到不可变呢?观察其源码: 而我们在上述的方法中, 提到的所有关于会改变字符串的方法,他其实都是新创建了一个对象 看以下代码 : public static void main(String[] args) { String str="*"; for (int i = 0; i < 20; i++) { str+=i; } System.out.println(str);//*012345678910111213141516171819 }我们去查看一下他的汇编: 由于效率太低,因此,引入另一种方法: 代码改进: public static void main(String[] args) { String str="*"; StringBuilder stringBuffer=new StringBuilder(); stringBuffer.app(str); for (int i = 0; i < 20; i++) { stringBuffer.app(i); } System.out.println(stringBuffer);//*012345678910111213141516171819 }不太明白吧?继续向下看咯: 8、StringBuilder和StringBuffffer StringBuilder 和 StringBuffffer也可以表示字符串,但他们不能直接赋值 使用举例: public static void main(String[] args) { StringBuilder stringBuilder=new StringBuilder("love"); System.out.println(stringBuilder);//love stringBuilder.reverse(); System.out.println(stringBuilder);//evol }这个字符串逆序,String类是没有这个方法的 从这可以观察到, StringBuilder 和StringBuffffer 与String类的区别,String对字符串内容变动时,都是需要新创建一个对象,并需要接收这个对象,而 StringBuilder 和 StringBuffffer 它们是对相应的字符串本身进行修改的,因此不需要接收。 总结StringBuilder与String类的区别 String: 1.String创建的对象是不可变的,一旦创建不可改变 2.对象值可以改变其实是创建了一个新的对象,然后把新的值保存进去 3.String类被final修饰,不可以被继承 4.String创建的对象的值存在于常量池,不用的时候不会被销毁 5.String运行时间较长 6.String适用于比较短而小的字符串 StringBuffer 1.StringBuffer创建的对象是可变的 2.它的改变不像String那样重新创建对象,而是通过构造方法 3.StringBuffer创建的对象的值存在于栈区,不用的时候会被销毁 4.StringBuffer运行时间较短 5.StringBuffer适用于比较长的字符串、比较多的字符串 StringBuilder 具体其他的方法,可以查看文档:http:// StringBuilder在线文档 补充:1、String与StringBuilder相互转换: public static void main(String[] args) { String str="love"; StringBuilder stringBuilder=new StringBuilder(str);//String变成了StringBuilder System.out.println(stringBuilder); }StringBuilder s = new StringBuilder("nice");String s = s.toString();面试题: 1. String 、 StringBuffffer 、 StringBuilder 的区别? String的内容不可修改,StringBuffffer与StringBuilder的内容可以修改. StringBuffffer与StringBuilder大部分功能是相似的 StringBuffffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程 不安全操 作 2. 以下总共创建了多少个 String 对象【前提不考虑常量池之前是否存在】 String str = new String ( "ab" ); // 会创建 2个对象 String str = new String ( "a" ) + new String ( "b" ); // 会创建 6个对象 第二题的不理解看图: toString转换会new新的对象: 9、OJ题巩固 题目一:字符串中的第一个唯一字符 题目描述: 两次遍历 count为计数数组(利用ASCII码,a对应97),一开始创建的count数组,里面所有值默认为0 第一次遍历, 用字符的ASCII码减去'a',得到的下标就与计数数组对应上了,将其加一 第二次遍历,将第一个为1的返回即可 代码: class Solution { public int firstUniqChar(String s) { int[] count=new int[26]; for(int i=0;i<s.length();i++) { char ch=s.charAt(i); count[ch-'a']++; } for(int i = 0;i<s.length();i++) { char ch=s.charAt(i); if(count[ch-'a']==1) { return i; } } return -1; }}测试通过: 题目二:字符串最后一个单词的长度 解法一:找到最后一个空格的位置,用总长度减去即可 代码: import java.io.InputStream;import java.util.Scanner;public class Main{ public static void main(String [] args) throws Exception{ Scanner sc=new Scanner(System.in); String str= sc.nextLine(); int n=str.lastIndexOf(' '); int x=str.length(); System.out.println(x-n-1); }}测试通过: 解法二:用字符串分割方法,输出其数组的最后一个字符串的长度 代码: import java.io.InputStream;import java.util.Scanner;public class Main{ public static void main(String [] args) throws Exception{ Scanner sc=new Scanner(System.in); String str= sc.nextLine(); String[] ret=str.split(" "); System.out.println(ret[ret.length-1].length()); }}测试通过: 题目三:检测字符串是否为回文 题目描述: 思路在代码中有注释: 代码: class Solution { //有效字符判断 public boolean isEffective(char ch) { return Character.isLetterOrDigit(ch); } public boolean isPalindrome(String s) { //统一大小写 s=s.toLowerCase(); int right=s.length()-1; int left=0; //回文判断 while(left<right) { while(left<right&&!isEffective(s.charAt(left))) { left++; } while(left<right&&!isEffective(s.charAt(right))) { right--; } if(s.charAt(left)!=s.charAt(right)) { return false; } left++; right--; } return true; }}测试通过:

标签: 云平台