
目录
2.2、boolean equal(Object anObject)方法,按照字典序(字符大小顺序)比较
2.4、compareToIgnoreCase方法:忽略大小写比较
8、StringBuilder和StringBuffffer
String类,在Java中属于字符串类型。
常用的三种构造字符串的方式:
代码:
- 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的内存分布:

例:
- 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);
- }
- }
运行结果如下:

但是这个比较只针对内置类型,对于引用类型,这么比较就是错误的,因为他比较的是值,也就是比较的是引用中的地址,并没有比较其指向的内容
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));
- }
- }
运行:

查看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
); - }
- 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
); - }
- }
运行结果:

例:
- public static void main(String[] args) {
- String str1="lyj";
-
- String str2="LYJ";
- System.out.println(str1.equalsIgnoreCase(str2));
-
- }
运行结果:

常用的方法总结:
| 方法 | 功能 |
| 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
-
- }
- 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
-
- }
- public static void main(String[] args) {
- String str1="family";
- System.out.println(str1.toUpperCase());//FAMILY
- String str2="LOVE";
- System.out.println(str2.toLowerCase());//love
- }
- 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...
- }
- public static void main(String[] args) {
- String s = String.format("%d-%d-%d", 2022, 8,12);
- //有点类似于printf
- System.out.println(s);//2022-8-12
- }
| 方法 | 功能 |
| 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
- }
| 方法 | 功能 |
|
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]
-
- }
| 方法 | 功能 |
| String substring(int beginIndex) | 从指定索引截取到结尾 |
| String substring(int beginIndex, int endIndex) | 截取部分内容 |
范例:
- 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
- }
String trim() 功能:去掉字符串中的左右空格,保留中间空格
范例:
- public static void main(String[] args) {
- String str=" hello world ";
- String ret=str.trim();
- System.out.println(ret);//hello world
- }
判断是否包含某字符串
- public static void main(String[] args) {
- String str="hellolyjhahaha";
- System.out.println(str.contains("lyj"));//true
- }
字符串常量池,其底层是一个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
- }
内存布局分析:

- 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对象中
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.append(str);
- for (int i = 0; i < 20; i++) {
- stringBuffer.append(i);
- }
- System.out.println(stringBuffer);//*012345678910111213141516171819
- }
不太明白吧?继续向下看咯:
使用举例:
- 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它们是对相应的字符串本身进行修改的,因此不需要接收。
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新的对象:

题目描述:

两次遍历
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
- char ch=s.charAt(i);
- count[ch-'a']++;
- }
- for(int i = 0;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
- while(left
isEffective(s.charAt(left))) { - left++;
- }
- while(left
isEffective(s.charAt(right))) { - right--;
- }
- if(s.charAt(left)!=s.charAt(right)) {
- return false;
- }
- left++;
- right--;
- }
- return true;
-
- }
- }
测试通过:


-
相关阅读:
Python编辑器和Pycharm的傻瓜式安装部署
vue2 解密图片地址(url)-使用blob文件-打开png格式图片
您需要了解的有关NFT的所有知识
在单链表中删除所有值为x的结点
vue3.0的变化汇总
(二)Ubuntu系统Pytorch环境配置
SQL:sql连接那些事儿
Ensembling Off-the-shelf Models for GAN Training(GAN模型迎来预训练时代,仅需1%的训练样本)
Python3《机器学习实战》学习笔记(四):朴素贝叶斯实战篇之新浪新闻分类
MySql学习笔记11——DBA命令介绍
-
原文地址:https://blog.csdn.net/LYJbao/article/details/126283199