一篇让你读懂java中的字符串(String)(三)

简介: 一篇让你读懂java中的字符串(String)(三)

字符串替换处理

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:

2.png


代码示例1:replaceAll方法

String str = "helloworld" ;
//结果为he__owor_d
System.out.println(str.replaceAll("l", "_"));

代码示例2:replaceFirst方法

String str = "helloworld" ;
//结果为he_loworld
System.out.println(str.replaceFirst("l", "_"));

代码示例3::replace方法

String str = "helloworld" ;
//结果为he__owor_d
System.out.println(str.replace("l", "_"));

可以发现replace方法与replaceAll方法的效果一样

来看下replace方法的源码吧:

2.png

可以看到replace方法的底层代码中的参数是CharSequence类型,但是我们自己传参的时候是string类型,这是为什么呢?

答:是因为发生了向上转型,String类实现了CharSequence这个接口,如下图所示:

2.png


注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串


字符串拆分(用的非常多,需要多注意)

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

可用方法如下:

2.png


代码示例1:split(String regex)方法

split方法返回的是一个String类型的数组,以下是多次拆分的代码,以后会经常出现

        String str = "username=zhangsan&password=123";
        //以“&”这个符号进行切割,切割一次后为username=zhangsan    password=123
        String[] strings = str.split("&");
        for (int i = 0; i < strings.length; i++) {
            //继续对第一次切割后的字符串进行切割
            String[] strings1 = strings[i].split("=");
            for (int j = 0; j < strings1.length; j++) {
            /*最终结果为:
            username
            zhangsan
            password
            123
            */
                System.out.println(strings1[j]);
            }
        }

还有我们会在leetcode刷题的时候经常遇见的使用空格来进行分割:

public class TestDemo5 {
    public static void main(String[] args) {
        //注意此处bcd与def之间有两个空格
        String str = "abc bcd  def";
        String[] str1 = str.split(" ");
        for (String s : str1) {
            System.out.println(s);
        }
    }
}
//输出结果为
abc
bcd
def

代码示例2:split(String regex,int limit)方法

limit=1说明只分了一组

        String str = "username=zhangsan&password=123";
        String[] strings = str.split("&",1);
        for (int i = 0; i < strings.length; i++) {
            //输出结果为username=zhangsan&password=123
            System.out.println(strings[i]);
        }

limit=2说明分为两组

        String str = "username=zhangsan&password=123";
        String[] strings = str.split("&",2);
        for (int i = 0; i < strings.length; i++) {
            /*输出结果为:
            username=zhangsan
            password=123
            */
            System.out.println(strings[i]);
        }

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义


代码示例3:特殊情况

情况1:拆分ip地址这类(单个分隔符)

String str = "192.168.1.1" ; 
String[] result = str.split("\\.") ; 
for(String s: result) {
 /*输出结果为
 192
 168
 1
 1
 */
    System.out.println(s);
}

像ip地址这种拆分的时候,如果是拿点号(.)进行拆分的话,需要进行转义,第一次转义是转义点号,第二次转义是保留转义符号的作用,意思就是让第一个\作为转义符号来使用


情况2:多个分隔符的拆分(使用连字符“|”)

        String str = "java-split#bit";
        //用|作为连字符,将-和#这两个分隔符进行拆分
        String[] strings = str.split("-|#");
        for (int i = 0; i < strings.length; i++) {
            /*输出结果为:
               java
               split
               bit
            */
            System.out.println(strings[i]);
        }

注意事项:


字符"|“,”*“,”+“都得加上转义字符,前面加上”\"


而如果是"“,那么就得写成”\\".


如果一个字符串中有多个分隔符,可以用"|"作为连字符.


字符串截取

从一个完整的字符串之中截取出部分内容。可用方法如下:

2.png


代码示例1:substring(int beginIndex)方法

        String str = "abcdefg";
        String str1= str.substring(3);
        //输出结果为:defg
        System.out.println(str1);

注意事项:


索引从0开始,3就是索引为3所对应的那个数字,也就是d


代码示例2:substring(int beginIndex,int endIndex)

        String str = "abcdefg";
        String str1= str.substring(0,5);
        //输出结果为:abcde
        System.out.println(str1);

从0下标开始截取,截取到4号下标,不包含5号下标所对应的字符

注意事项:


注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

1

其他操作方法

2.png


trim方法

trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等).

public class string {
    public static void main(String[] args) {
        String str = "   abc  de fg   ";
        //输出结果为:   abc  de fg   
        System.out.println(str);
        String str1=str.trim();
        //输出结果为:abc  de fg
        System.out.println(str1);
    }
}

toUpperCase方法

public class string {
    public static void main(String[] args) {
        String str = "abc";
        String str1=str.toUpperCase();
        //输出结果为:ABC
        System.out.println(str1);
    }
}

toLowerCase方法

public class string {
    public static void main(String[] args) {
        String str = "ABabc";
        String str1=str.toLowerCase();
        //输出结果为:ababc
        System.out.println(str1);
    }
}

注意事项:toUpperCase方法和toLowerCase方法这两个方法只转换字母,不转换中文字符。


intern方法(前面已经讲过)

concat方法(不经常用,不做过多赘述)

length方法

public class string {
    public static void main(String[] args) {
        String str = "abc";
        int length=str.length();
        //输出结果为:3
        System.out.println(length);
    }
}

注意事项:数组长度使用数组名称.length属性,而String中使用的是length()方法


isEmpty方法

public class string {
    public static void main(String[] args) {
        //定义一个空字符串
        String str = "";
        boolean boolean1=str.isEmpty();
        //输出结果为:true
        System.out.println(boolean1);
    }
}

注意有两种方式可以表示空字符串

第一种方式:String str=“”,这种方式代表指向的字符串对象什么都没有.

第二种方式:String str=null,这种方式代表不指向任何对象


join方法

2.png


StringBuffer 和 StringBuilder

首先给出其官方网址:

StringBuffer 类:点我进入官网

StringBuilder 类:点我进入官网

首先来回顾下String类的特点:

任何的字符串常量都是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指向而已。

通常来讲String的操作比较简单,但是由于String的不可更改特性,为了方便字符串的修改,提供StringBuffer和StringBuilder类。

StringBuffer 和 StringBuilder 大部分功能是相同的,我们主要介绍 StringBuffer

在String中使用"+"来进行字符串连接,但是这个操作在StringBuffer类中需要更改为append()方法


使用了append方法进行拼接后,新产生的字符串在字符串常量池就不再生成内存了,就直接在原内存上的字符串进行拼接


代码示例

public class string {
    public static void main(String[] args) {
        //append方法的字符串拼接是在原字符串基础上进行拼接的,并不是生成新的字符串
        StringBuffer stringBuffer=new StringBuffer("abcd");
        //输出结果为abcdefg
        System.out.println(stringBuffer.append("efg"));
    }
}

为什么append方法会在原字符串上进行拼接呢?

来看append方法的源码:

2.png

最后返回的是当前对象的引用(return this),所以就是在原字符串上进行拼接.

append方法可以传的参数类型很多:例如char[],char ,boolean,int,long,float,double,StringBuffer,CharSequence


String与StringBuffer(StringBuilder)的转换

String和StringBuffer(StringBuilder)类不能直接转换。如果要想互相转换,可以采用如下原则:

String变为StringBuffer(StringBuilder):利用StringBuffer(StringBuilder)的构造方法或append()方法 (常用)

StringBuffer(StringBuilder)变为String:调用toString()方法。(常用)


总结

String与StringBuffer,StringBuilder的区别(面试题)

StringBuffer,StringBuilder包含了一些String没有的方法 比如reverse方法


StringBuffer,StringBuilder是可变的,String是不可变的。String的每次拼接,都会产生新的对象。

StringBuffer,StringBuilder每次的拼接都返回的是this,说明是在原字符串上进行拼接的.


StringBuffer与StringBuilder区别(面试题)

先来看StringBuffer,StringBuilder的append方法:

StringBuffer类中的append方法是被synchronized修饰的,

这个关键字可以保证线程的安全.

2.png2.png


总结:


StringBuilder和String 出现在单线程情况下

StringBuffer因为有synchronized关键字,所以一般出现多线程情况下。


一般来说非多线程的情况下最好使用StringBuilder,原因是 synchronized关键字涉及到锁的问题,每次的开锁关锁都要消耗资源


StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作


String与StringBuilder区别(面试题)

既然都运用于单线程的情况下,那么这两者到底有什么区别呢?

1:String的拼接”+“会被优化 优化为StringBuilder中的append方法,来看分析:

我们将下面这段代码进行编译:

public class string {
    public static void main(String[] args) {
        String str="abc";
        str=str+"de";
        System.out.println(str);
    }
}

编译后得到的如下图所示:

2.png

可以看到底部进行了优化,那么对于上述代码来说其实底层在运行的时候的代码如下所示:(代码的执行方式跟图中是一样的)

public class string {
    public static void main(String[] args) {
        String str="abc";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str);
        stringBuilder.append("hello");
        String str1 = stringBuilder.toString();
        System.out.println(str1);
    }
}

所以说对于String类的”+“的拼接,底层虽然是StringBuilder类的append方法的优化,但是其仍然会产生大量的临时空间

再来看之前遗留的一个问题:

   public static void main(String[] args) {
        String str = "abc";
        for(int i = 0;i < 10;i++) {
            str += i;
        }
        System.out.println(str);
    }

上述代码之前我们说因为由于”+“号的拼接,导致会产生大量的临时变量,此时我们来使用StringBuilder的append方法来进行优化:


public class string {
    public static void main(String[] args) {
        String str = "abc";
        //在循环外定义StringBuilder对象
        StringBuilder sb = new StringBuilder();
        sb.append(str);
        for (int i = 0; i < 10; i++) {
             //循环内部使用append方法
            str  = sb.append(i).toString();
        }
        System.out.println(str);
    }
}

2:在循环当中 不可以使用String直接进行拼接 这样会产生大量的临时对象

包括优化之后的StringBuilder对象。所以每次定义StringBuilder对象的时候在循环外进行定义,然后在循环内部使用append方法.


小结

字符串操作是我们以后工作中非常常用的操作. 使用起来都非常简单方便, 一定要使用熟练. 指的注意的点:

1.字符串的比较, ==, equals, compareTo 之间的区别.

2.了解字符串常量池, 体会 “池” 的思想.

3.理解字符串不可变

4.split 的应用场景

5.StringBuffer 和 StringBuilder 的功能.


String练习题

练习题1

下面代码将输出什么内容:()

2.png

A.true

B.false

C.1

D.编译错误


答:B


原因是toLowerCase方法实际上返回值是一个新的字符串,我们来看源码:

2.png

再点toLowerCase:

2.png

可以看到返回的是new String这样的字符串,所以它的地址是对象中value数组的地址,而"admin"是存储在字符串常量池的,所以两者地址肯定不同.


练习题2

指出下列程序运行的结果()

2.png

A.good and abc

B.good and gbc

C.test ok and abc

D.test ok and gbc


答案:B
相关文章
|
3月前
|
SQL JSON Java
告别字符串拼接:用Java文本块优雅处理多行字符串
告别字符串拼接:用Java文本块优雅处理多行字符串
422 108
|
3月前
|
Python
Python中的f-string:更优雅的字符串格式化
Python中的f-string:更优雅的字符串格式化
354 100
|
3月前
|
开发者 Python
Python中的f-string:高效字符串格式化的利器
Python中的f-string:高效字符串格式化的利器
476 99
|
3月前
|
Python
Python中的f-string:更优雅的字符串格式化
Python中的f-string:更优雅的字符串格式化
|
3月前
|
开发者 Python
Python f-string:高效字符串格式化的艺术
Python f-string:高效字符串格式化的艺术
|
4月前
|
Python
Python中的f-string:更简洁的字符串格式化
Python中的f-string:更简洁的字符串格式化
319 92
|
2月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
325 5
|
4月前
|
存储 SQL 缓存
Java字符串处理:String、StringBuilder与StringBuffer
本文深入解析Java中String、StringBuilder和StringBuffer的核心区别与使用场景。涵盖字符串不可变性、常量池、intern方法、可变字符串构建器的扩容机制及线程安全实现。通过性能测试对比三者差异,并提供最佳实践与高频面试问题解析,助你掌握Java字符串处理精髓。
|
5月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
372 14