初始Java篇(JavaSE基础语法)(8)认识String类(下)

05-28 1070阅读

找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏:JavaSE

接上文 初始Java篇(JavaSE基础语法)(8)认识String类(上)-CSDN博客

目录

字符串截取

其他操作方法

字符串的不可变性 

字符串修改

StringBuilder和StringBuffer

刷题练习

387.字符串中第一个唯一字符 

HJ1 字符串最后一个单词的长度 

 125.验证回文串


字符串截取

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

方法功能
String substring(int beginIndex)从指定索引的位置截取到结尾
String substring(int beginIndex, int endIndex)截取部分内容(从beginIndex位置到endIndex位置)

注意:

1. 索引从0下标开始。

2. 注意前闭后开区间的写法。substring(0, 5) 表示从0下标开始截取,一直到4下标,即[0,5) 。

示例: 

初始Java篇(JavaSE基础语法)(8)认识String类(下)

其他操作方法

方法功能
String trim()去掉字符串中的左右空格,保留中间空格

示例:初始Java篇(JavaSE基础语法)(8)认识String类(下)

字符串的不可变性 

String是一种不可变对象。字符串中的内容是不可改变。字符串不可被修改。下面就是String的源码:

初始Java篇(JavaSE基础语法)(8)认识String类(下)

这里可能会有小伙伴会说是因为value数组被 final 修饰了,因此这个数组的内容就不可变了,也就是说这个数组里面存放的字符就不可修改了。

其实不然,这个final修饰的数组,只是让这个数组名,也就是数组对象的引用不能被修改了,并不是说这个数组的内容不能被修改了。

例如:初始Java篇(JavaSE基础语法)(8)认识String类(下)

final修饰引用类型表明该引用变量不能去引用其他对象了,但是其引用对象中的内容是可以修改的。 

那既然如此,是什么不能让我们修改String的内容呢?其实是 private 修饰的整个数组。如果我们想要修改这个数组内容首先得拿到这个数组吧,但是 private 修饰就直接导致我们拿不到这个数组。因此我们就根本没有机会去修改这个数组。这也就是 String 不可修改的原因。

那可能小伙伴又有疑惑了:既然不能修改String,那前面我们学习的拆分字符串,字符串大小写转换……这些不都改变了字符串本身吗?这只是我们看到的表面现象。所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象 。这样我们每一次涉及修改字符串的操作都是创建一个新的对象。

为什么 String 要设计成不可变的?(不可变对象的好处是什么?) (目前简单了解)

1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了。

2. 不可变对象是线程安全的。 

3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中. 那如果想要修改字符串中内容,该如何操作呢?

字符串修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。例如:

public class Test {
    public static void main(String[] args) {
        String s = "hello";
        System.out.println(s);
        s += " world";
        System.out.println(s);
    }
}

那么怎样才能使效率变得更高呢?

借助StringBuffer 和 StringBuilder。下面就来介绍一下。

StringBuilder和StringBuffer

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的。

看到这里,可能有小伙伴要问了:String不是不可修改吗?怎么又说为了方便修改提供了这两个类呢?这不就前后矛盾了吗?

不不不,并不矛盾。正是因为String不可修改,所以当我们想要修改String时,做不到。那么java开发人员也想到了这种情况,因此就设计出了StringBuffer和StringBuilder这两个类,来让我们想要修改时,可以做到。做法是通过StringBuffer和StringBuilder,修改传入的字符串,再把修改后的结果转换为字符串。这就是字符串的修改方式。

这里介绍 StringBuffer常用的一些方法。

StringBuff append(String str)  在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        sb.append(" world");
        System.out.println(sb);
    }
}

char charAt(int index) 获取index位置的字符。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.charAt(0));
    }
}

int length() 获取字符串的长度 。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.length());
    }
}

int capacity()    获取底层保存字符串空间总的大小 。 

这里的底层是指用 c/c++ 保存时的大小。不必关心,

void ensureCapacity(int mininmumCapacity)     扩容。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        // 把空间扩充到原来的两倍
        sb.ensureCapacity(sb.length()*2);
    }
}

void setCharAt(int index, char ch)   将index位置的字符设置为ch 。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        sb.setCharAt(4, 'O');
        System.out.println(sb);
    }
}

 int indexOf(String str)    返回str第一次出现的位置。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        //                         这里要是字符串
        System.out.println(sb.indexOf("o"));
    }
}

int indexOf(String str, int fromIndex)      从fromIndex位置开始查找str第一次出现的位置 。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.indexOf("o", 2));
    }
}

StringBuff insert(int offset, String str)         在offset位置之前插入:八种基类类型 & String类型 & Object类型数据 。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        //                         在4位置之前,插入world
        System.out.println(sb.insert(4, " world"));
    }
}

StringBuffer deleteCharAt(int index)     删除index位置字符。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.deleteCharAt(0));
    }
}

StringBuffer delete(int start, int end)     删除[start, end)区间内的字符。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        //                   删除的范围是[0,4)
        System.out.println(sb.delete(0, 4));
    }
}

StringBuffer replace(int start, int end, String str)    将[start, end)位置的字符替换为str。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        //               把[0,4)内的字符串内容替换成空,相当于删除操作
        System.out.println(sb.replace(0, 4, ""));
    }
}

String substring(int start)          从start开始一直到末尾的字符以String的方式返回。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.substring(0));
    }
}

String substring(int start,int end)                 将[start, end)范围内的字符以String的方式返回。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        //                  返回的是[0,4)之间的字符串
        System.out.println(sb.substring(0, 4));
    }
}

StringBuffer reverse()         反转字符串。

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.reverse());
    }
}

String toString()                 将所有字符按照String的方式返回。 

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println(sb.toString());
    }
}

StringBuilder 的用法也和上面的类似。

StringBuffer 、StringBuilder 和String的区别:显而易见,前面两个是可以直接修改的,而String不行,只能通过创建出新的对象。而这个修改可变不可变主要是看是否可以在原对象上进行修改。其次,两者的方法也有些差异。

刷题练习

387.字符串中第一个唯一字符 

给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。

示例 1:

输入: s = "leetcode"
输出: 0

示例 2:

输入: s = "loveleetcode"
输出: 2

示例 3:

输入: s = "aabb"
输出: -1

提示:

  • 1
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]