知识改变命运 第九集:认识Java中的Sting类

**前言:**我们先思考一个问题,在c语言中有字符串类型吗?答案是没有的,这时候有人问明明有啊?

char *p="abcde";

这不就是字符串类型吗?答案是否定的,上面这段代码p变量本质是指针,它内部里面只是存储了字符串中首元素a的地址。而且在c语言中它是以\0来判断字符串是否结束的,在字符串末尾都有一个因此的\0,如下图
在这里插入图片描述
但是在Java中对于字符串我们有专门的类型——String类(引用类型)

1String类常用的构造方法

首先我们看一下String类型的全部构造方法如图;
在这里插入图片描述
但是我们常用的就这三种——

String str="abcde";//1使用常量串构造
String str=new String(abcde);//2 直接newString对象
char []array={'a','b','c','d','e'};//3使用字符数组进行构造
String str=new String(array);

在这里插入图片描述
接下来我们研究下面的代码,了解String中的实际存储情况

ublic static void main(String[] args) {
        String s1=new String("abcde");
        String s2=new String("hello world");
        String s3=s1;

        System.out.println(s1.length());//获得一个字符串长度
        System.out.println(s1.isEmpty());//判断一个字符串是否为0,返回ture或者false
    }

我们花了一个内存存储图方便大家来理解”为什么引用类型本身不存储字符串”
在这里插入图片描述
上图很好的解释了,String是引用类型,内部并没有直接存储字符串这句话。s1和s2内部是存储了value这个数组的地址,而数组又存储了字符串常量的地址。

1.1字符串的长度

s1.length();//1
 "abced".length();//2

以上两种方式都可以获得字符串的长度
为什么第2种也可以呢?答:在Java中" "引起来的也是String类型对象。

1.2判断一个字符串是否为0

s1.isEmpty();
0返回true0返回false

0返回true 非0返回false;
我们要注意下
这里的0不是null,如果s1=null代表s1不指向任何对象。

1.3String对象的比较

字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4中方式:

  1. == 比较是否引用同一个对象
    注意:对于内置类型, == 比较的是变量中的值;对于引用类型 == 比较的是引用中的地址。
    对于引用类型,所以我们不能直接用 == 比较。

我们借助 boolean equals(Object anObject) 方法:按照字典序比较 字典序:字符大小的顺序
String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照 如下规则进行比较,比如: **s1.equals(s2) **
相等返回true不相等返回false

—————————————————————————————————————————————————

int compareTo(String s) 方法: 按照字典序进行比较
与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:
1先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
2如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值

—————————————————————————————————————————————————

  1. int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较

2字符串的查找

方法功能
char charAt(int index)返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常
int indexOf(int ch)返回ch第一次出现的位置,没有返回-1
int indexOf(int ch, intfromIndex)从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str)返回str第一次出现的位置,没有返回-1
int indexOf(String str, int fromIndex)从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch)从后往前找,返回ch第一次出现的位置,没有返回-1
int lastindex(int ch,fromindex)从formindex位置从后往前找ch,返回第一次出现ch的位置,没有返回-1
int lastIndexOf(String str)从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, intfromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1

3转化

3.1数值和字符串的转换

在这里插入图片描述

3.2大小写转换

 String str1="abcdA";
        String str2=str1.toLowerCase();
        String str3=str1.toUpperCase();
        System.out.println(str2);//abcda
        System.out.println(str3);//ABCDA

3. 2字符串转数组

public static void main(String[] args) {
String s = "hello";
// 字符串转数组
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
System.out.print(ch[i]);
}
System.out.println();
// 数组转字符串
String s2 = new String(ch);
System.out.println(s2);

3.3格式化

public static void main(String[] args) {
String s = String.format("%d-%d-%d", 2019, 9,14);
System.out.println(s);
}

3.4字符串替换

 String str1="abababababab";
        String str2=str1.replace("ab","n",);
        String str3=str1.replaceAll(str1,"c");
        String str4=str1.replaceFirst("ab","c");
        System.out.println(str4);
        System.out.println(str3);
        System.out.println(str2);

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

3.5字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
可用方法如下:

String[] split(String regex) 将字符串全部拆分
String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组

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

String str = "192.168.1.1" ;
String[] result = str.split("\\.") ;
for(String s: result) {
System.out.println(s);
}

注意事项:

  1. 字符"|“,”*“,”+"都得加上转义字符,前面加上 “\” .
  2. 而如果是 “” ,那么就得写成 “\\” .
  3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.
    代码示例: 多次拆分
 String str1="198#-12#.1_3";
        String[]array=str1.split("-");
        for (String x:array) {
            String[] xx=x.split("#");
            for (String ss: xx) {
                System.out.println(ss);

3.6字符串截取

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

String substring(int beginIndex) 从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容

代码示例: 观察字符串截取

String str = "helloworld" ;
System.out.println(str.substring(5));
System.out.println(str.substring(0, 5));

注意事项:

  1. 索引从0开始
  2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

3.8其他操作方法

String trim() 去掉字符串中的左右空格,保留中间空格
String toUpperCase() 字符串转大写
String toLowerCase() 字符串转小写

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

代码示例: 观察trim()方法的使用

String str = " hello world " ;
System.out.println("["+str+"]");
System.out.println("["+str.trim()+"]");

代码示例: 大小写转换

String str = " hello%$$%@#$%world 哈哈哈 " ;
System.out.println(str.toUpperCase());
System.out.println(str.toLowerCase());

这两个函数只转换字母。

4字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:

  1. String类在设计时就是不可改变的,String类实现描述中已经说明了
    以下来自JDK1.8中String类的部分实现:
    在这里插入图片描述
    在这里插入图片描述
    String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:
  2. String类被final修饰,表明该类不能被继承
  3. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。
  4. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
    比如 replace 方法
    在这里插入图片描述
    【纠正】网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。
    final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。
public static void main(String[] args) {
final int array[] = {1,2,3,4,5};
array[0] = 100;
System.out.println(Arrays.toString(array));
// array = new int[]{4,5,6}; // 编译报错:Error:(19, 9) java: 无法为最终变量array分配值
}

为什么 String 要设计成不可变的?(不可变对象的好处是什么?) (选学)

  1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
  2. 不可变对象是线程安全的.
  3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
    那如果想要修改字符串中内容,该如何操作呢

5 字符串修改

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

public static void main(String[] args) {
String s = "hello";
s += " world";
System.out.println(s); // 输出:hello world
}

但是这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象

在这里插入图片描述

public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "";
for(int i = 0; i < 10000; ++i){
s += i;
}
long end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for(int i = 0; i < 10000; ++i){
sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for(int i = 0; i < 10000; ++i){
sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
}

可以看待在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder。

6 StringBuilder和StringBuffer

6.1 StringBuilder的介绍

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的,这里介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅 StringBuilder在线文档

StringBuff append(String str)
在尾部追加,相当于String+=,可以追加:booleancharchar[]doublefloatintlongObjectStringStringBuff的变量
char charAt(int index) 获取index位置的字符
int length() 获取字符串的长度
int capacity() 获取底层保存字符串空间总的大小
void ensureCapacity(int mininmumCapacity)
扩容
void setCharAt(int index,char ch) 将index位置的字符设置为ch
int indexOf(String str) 返回str第一次出现的位置
int indexOf(String str, int fromIndex)从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str) 返回最后一次出现str的位置
int lastIndexOf(String str,int fromIndex)从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(int offset, String str) 在offset位置插入:八种基类类型 & String类型 & Object类型数据 StringBuffer
deleteCharAt(int index) 删除index位置字符
StringBuffer delete(int start, int end) 删除[start, end)区间内的字符
StringBuffer replace(int start, int end, String str)[start, end)位置的字符替换为str
String substring(int start) 从start开始一直到末尾的字符以String的方式返回
String substring(int start,int end)[start, end)范围内的字符以String的方式返回
StringBuffer reverse() 反转字符串
String toString() 将所有字符按照String的方式返回

在这里插入图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值