Java string类

Java String 类

字符串的构造:

常用的3种方式:

public class Create_string {
    public static void main(String[] args) {
    
        String s1="qwdj1238385";//直接创建;编译器会根据值创建对象
        String s2=new String("nfihwj2393-");//通过构造方法创建
      
        char []arr={'a','s','c'};//字符数组
        String s3=new String(arr);
        System.out.println(s3);//输出asc
        //java的字符串是不会像c语言那样后面有个/0结尾

    }
}

String使用

字符串的比较:

1:是否相等

引用类型的比较不能使用 = =;得使用equals方法。
数组是Object对象,如果直接使用equals方法,实质上还是使用==比较。我们的String,Arrays类都重写了equles方法。

import java.util.Arrays;

public class test7 {
    public static void main(String[] args) {

        String s1="qqq";
        String s2=new String("qqq");
        System.out.println(s1==s2);           //false
        System.out.println(s1.equals(s2));   //true
        System.out.println(s1.equalsIgnoreCase(s2));//忽略大小写比较
        int []arr1={1,2,3};
        int []arr2={1,2,3};
        System.out.println(arr1==arr2);     //false
        System.out.println(arr1.equals(arr2));  //false
        System.out.println(Arrays.equals(arr1,arr2));   //true
    }
}

2:比较大小
String已经实现Comparable接口且重写compareTo方法
所以我们直接使用就行;返回int 类型,他们的差值。是先比较第一个,如果第一个相等就继续比较第二个字符。直到比完如果相等就返回0。

public class test8 {//字符串的比较大小
    public static void main(String[] args) {
        String s1="abe";
        String s2=new String("abc");
        System.out.println(s1.compareTo(s2)); //2
    }
}

如果是前面都相等的情况下,那么谁的字符个数多则比较大。返回相差的字符个数字符

public class test8 {
    public static void main(String[] args) {
        String s1="abceeee";
        String s2=new String("abc");
        System.out.println(s1.compareTo(s2)); //4
        System.out.println(s1.compareToIgnoreCase(s2));//忽略大小写比较
    }
}

字符串查找

1:从前往后找

public class test9 {//查看字符串
    public static void main(String[] args) {
        String s1="abccdefg";
        System.out.println(s1.indexOf('p'));//在字符串查找某个字符的位置,如果没有返回-1
        System.out.println(s1.indexOf('c',3));//从下标为3开始找
    
        System.out.println(s1.indexOf("bcc"));  //查找字符串的位置
        System.out.println(s1.indexOf("bcc",3));  //从3下标开始查找字符串的位置

       
    }
}

2:从后往前找

public class test9 {//查看字符串
    public static void main(String[] args) {
        String s1="abccdefg";

        System.out.println(s1.lastIndexOf('c'));
        System.out.println(s1.lastIndexOf('c',5)); //从5下标开始往前找
        
        System.out.println(s1.lastIndexOf("abc"));
        System.out.println(s1.lastIndexOf("ajff",5)); //从5下标开始往前找
    }
}

转化为字符串类型

public class test10 {
    public static void main(String[] args) {
        //类名调用,static方法
        String s1=String.valueOf(123);//数字转字符
         System.out.println(s2);//123
        String s2=String.valueOf(new student(18,"str"));
        System.out.println(s2);     //这时候打印是地址,没转化成功
    }                             
}
 class student {

    int age=100;
 String name;

   
}

转化的前提是得重写了tostring方法。源码是如果自己没有重写toString方法它则去调用Object的。
在这里插入图片描述
重写的代码:(步骤:鼠标右键,Generate,选择toString)

  @Override
    public String toString() {
        return "student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

重写后输出结果:
在这里插入图片描述

字符串类型转成其它类型

public class test11 {
    public static void main(String[] args) {

        int a1=Integer.parseInt("123"); //转int类型
        int a2=Integer.valueOf("123");            
        double a3=Double.parseDouble("12.3");//其它类型都是类似方法
    }
}

大小写的英文字母互相转换

public class tset12 {
    public static void main(String[] args) {
        String s="abc";
        String s1=s.toUpperCase();//小转大
        System.out.println(s);
        System.out.println(s1);
        String s3=s1.toLowerCase();//大转小
        System.out.println(s3);
    }
}

输出:
abc
ABC
abc

注意:String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了,我们并不是在原来的那一份上修改。

字符串转数组

public class test13 {
    public static void main(String[] args) {
        String s1="1ewjdh";
        String s2="djff";
        char []arr1=s1.toCharArray();
    }
}

格式化字符串(使用比较少)

推荐参考
在这里插入图片描述

字符串替换

在这里插入图片描述

public class test13 {
    public static void main(String[] args) {
        String s1 = "abcccddecdg";
        String s2 = s1.replace('c', 'd');//把所有的c换成d
        System.out.println(s2);
        String s3 = s1.replace("cd", "sq");//把所有的cd换成sq
        System.out.println(s3);
        String s4 = s1.replaceAll("cd", "sq");//也是把所有的cd换成sq,这个方法得是字符串才能用
        System.out.println(s4);
        String s5 = s1.replaceAll("c", "d");
        System.out.println(s5);
        String s6=s1.replaceFirst("cd","sq");//把第一个出现的cd换成sq,也是只能用字符串
        System.out.println(s6);
    }}

输出结果:
abdddddeddg
abccsqdesqg
abccsqdesqg
abdddddeddg
abccsqdecdg

字符串拆分

把一个完整的字符串按照指定的分隔符划分为若干个子字符串;返回的结果是字符串数组。

import java.util.Arrays;

public class test14 {
    public static void main(String[] args) {
        String s1="wnjksnaasjeda";
        String []arr=s1.split("s");
        String []arr1=s1.split("s",2);//设置只划分为两个子字符串
        System.out.println(Arrays.toString(arr));
        
        char [] a={'1','2'};
        System.out.println(a);
    }
}

在这里插入图片描述

特殊情况:需要加转义字符。

import java.util.Arrays;

public class test14 {
    public static void main(String[] args) {
        String s1="127.123.455";
        String []arr=s1.split("\\.");
        System.out.println(Arrays.toString(arr));
        
    }
}

转义字符也需要转义字符来修饰,所以就是两个\最终发挥一个作用。如果我们要使用\来划分就需要\\(| * +都得需要转义字符)

多个分隔符的情况。使用| 分隔开

import java.util.Arrays;

public class test14 {
    public static void main(String[] args) {
        String s1="127.123.4&55";
        String []arr=s1.split("\\.|&");
        System.out.println(Arrays.toString(arr));

    }
}

输出:[127, 123, 4, 55]

字符串截取

public class test12 {
    public static void main(String[] args) {
        String s1="helooworld";
        String s2=s1.substring(5);//从5位置往后截取
        System.out.println(s2);
        
        String s3=s1.substring(5,9);//截取【5-10)区间字符
        System.out.println(s3);
    }
}

输出:
world
worl

去掉字符串两边空格(空格, 换行, 制表符等)

public class test12 {
    public static void main(String[] args) {
        String s1="  hel  ooworld  ";
        String s2=s1.trim();
        System.out.println(s2);
    }
}

输出:hel ooworld

判断字符串是否包含子字符串

public class test12 {
    public static void main(String[] args) {
        String s1="  hel  ooworld  ";
        System.out.println(s1.contains("h"));//true
    }
}

判断以…字符串开始

public class test12 {
    public static void main(String[] args) {
        String s1="hel  ooworld  ";
        System.out.println(s1.startsWith("hel"));//判断是否从这个字符串开始
    }
}

字符串类型你能想到的字符串操作,他都有实现的方法,我们在后续练习和学习还是会和数组就是操作字符串打很多交道。需要用到其它方法的时候 官方文档查看

字符串内存储存

String源码:String是引用类型里边并不储存字符串,而是储的它的引用。
在这里插入图片描述
调试一下,可以看到确实是如此。
在这里插入图片描述

字符串常量池:
String内存储存是比较特殊;因为他里面有一个字符串常量池;字符串常量池在方法区(元数据)里边(以前的jdk版本是在堆);底层是一个String Table哈希表(数组与链表的组合;所以说源码点进去有一个hash值的属性)
当我们使用字面值或使用String类的intern()方法创建字符串常量时,如果字符串常量池中已经存在相同内容的字符串(通过计算字符串的哈希值判断在常量池的这个哈希表是否能找到),JVM会返回该字符串对象的引用(new的话是一定会创建一个新的引用对象;在常量池存的是引用对象)。如果字符串常量池中不存在这个字符串,JVM会创建一个新的字符串对象,并将其引用对象添加到字符串常量池中。

字符串常量池的影响下:常量池存的是引用对象
在这里插入图片描述
我们可以使用==和equals比较它们各自的关系;最后通过图片的总结展示内存效果。
s1和s2:JVM会首先检查字符串常量池中是否已经存在相同内容的字符串对象,如果存在,则s1和s2会被指向同一个字符串对象。(带双引号号的在常量池只有一份;0x00这个节点还可以有其它的存有字符串对象;因为是一个链表)

在这里插入图片描述

s3和s1:直接常量池判断有相同的引号字符串;就返回这个0x89的对象。这就是常量池的特殊之处;如果你是数组;如果a的引用是0x88;b=a;那么b的引用是0x99;找到的是0x88。

s4和s5:对象是不一样;但是对象里面的value是一样。对象就不再是0x98;而是new新的;但是里面的value都是0x11。它们使用的都是同一份"hello"

s6也是和s4、s5如此

题目1:
在这里插入图片描述

题目2:
在这里插入图片描述
题目3:
“abc”+“def"编译的时候就是相当于"abcdef”,所以4执行,6不执行。
在这里插入图片描述

intern方法

intern()方法是String类提供的一个方法,它的作用是在字符串常量池中查找当前字符串对象,如果常量池中存在相同内容的字符串,则返回常量池中的对象引用,如果常量池中不存在相同内容的字符串,则将当前字符串对象添加到常量池中,并返回常量池中的对象引用。

字符数组对象不会直接存储在字符串常量池中;如果我们使用new (字符串数组)的方式创建字符串;字符串不会自动存储到字符串常量池中;我们可以使用该方法手动将创建的String对象添加到常量池中。

public static void main(String[] args) {
char[] ch = new char[]{'a', 'b', 'c'};
String s1 = new String(ch); // s1对象并不在常量池中,
s1.intern(); // s1.intern();调用之后,会将s1对象的引用放入到常量池中
String s2 = "abc"; // "abc" 在常量池中存在了,s2创建时直接用常量池中"abc"的引用
System.out.println(s1 == s2);  //输出true
}

三种创建方式内存不同的总结

  1. String str = “hello”:在堆开辟一块内存空间,然后保存到字符串常量池,再给String引用。创建两个对象数组+String对象

  2. String str = new String(“hello”) : 会开辟两块堆内存空间,1:字符串"hello" 2: 然后用常量池中的String对象给新开辟的String对象赋值。创建3个对象(常量池啥也没有的情况)
    在这里插入图片描述

  3. String str = new String(new char[]{‘h’, ‘e’, ‘l’, ‘l’, ‘o’}) :先在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内容拷贝到String对象中(把hello字符数组拷贝一份给String)。创建数组,数组的拷贝,String对象
    (char数组是不会直接放入常量池的,在这个构造中:this.value = Arrays.copyOf (value, value.length),是对实参变量做了拷贝,存储在堆中)

字符串的不可变

1:我们操作的字符串原来的是不会改变的,都是新建。看一下源码分析。
在这里插入图片描述

字符串的修改

不建议在String类型对象进行修改,因为每一次修改都会创建很多对象.

public class test22 {
    public static void main(String[] args) {
        String s1="hello";
       s1+="world";
    }
}     //一个简简单单拼接光String对象就创建了3个(hello,world,helloworld)

可以看到两个代码的时间差别是非常的大
在这里插入图片描述

StringBuilder和StringBuffer

1 :StringBuilder和StringBuffer类。这两个类大部分功能是相同的
2 :String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。

public class test22 {
    public static void main(String[] args) {
StringBuffer s=new StringBuffer("abc");
 long start=System.currentTimeMillis();
        for (int i = 0; i <100000 ; i++) {
         s.append(i);//追加i字符串
        }
        long end=System.currentTimeMillis();
        System.out.println(end-start);//13
    }
}

两者之间转换:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法。

        String str = "abcde";
        StringBuilder str0 = new StringBuilder(str);
 //StringBuilder str0= new StringBuilder();
//sb.append(str);

        String str = "abcde";
        StringBuilder str0 = new StringBuilder();
        str0.append(str); 
        
        str = s1.toString(); 

StringBuilder官方文档
String、StringBuffer、StringBuilder的区别

1: String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
2: StringBuffer与StringBuilder大部分功能是相似的
3: StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞭望~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值