Java string类

  • Post author:
  • Post category:java




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内存储存是比较特殊;因为他里面有一个字符串常量池;字符串常量池在堆里边;底层是一个String Table哈希表(数组与链表的组合):

当我们使用字面值或使用String类的intern()方法创建字符串常量时,如果字符串常量池中已经存在相同内容的字符串,JVM会返回该字符串对象的引用。如果字符串常量池中不存在这个字符串,JVM会创建一个新的字符串对象,并将其添加到字符串常量池中。

字符串常量池的影响下:

在这里插入图片描述

我们可以使用==和equals比较它们各自的关系;最后通过图片的总结展示内存效果。

s1和s2:JVM会首先检查字符串常量池中是否已经存在相同内容的字符串对象,如果存在,则s1和s2会被指向同一个字符串对象。(带双引号号的在常量池只有一份;0x00这个节点还可以有其它的存有字符串对象;因为是一个链表)

在这里插入图片描述

s3和s1:直接常量池判断有相同的引号字符串;就返回这个0x89的对象

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未采用同步处理,属于线程不安全操作



版权声明:本文为m0_64254651原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。