Java小技能:字符串

79 阅读7分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情

引言

String,StringBuffer,StringBuilder,char[],用来表示字符串。

I 预备知识

1.1 Object类

是所有类的根类

toString():打印格式为全限定名@hashCode。

注:全限定名=包名+类名,包名与类名使用点号连接,用来唯一标识一个类。

在输出对象时,默认调用对象的toStirng方法。

个人推荐使用如下重写toString,有更高的兼容性:

	@Override
	public String toString() {
		return org.apache.commons.lang.builder.ReflectionToStringBuilder.toString(this);
	}

equals():在Object中比较的是对象的地址是否相等 sun建议:重写equals方法时,保证两个相同内容的对象作比较的结果为true,来达到equals方法比较对象的内容,

==运算符比较的是对象地址的目的。

1.2 重写的规则

  1. 自反性:如果对象o非空,那么o.equals(o)的放回值为TRUE。
  2. 对称性:如果对象x,y非空,那么x.equals(y)与y.equals(x)的放回值一样。
  3. 传递性:如果对象x,y,z非空,如果x.equals(y)的放回值为TRUE,y.equals(z)的放回值为TRUE,那么 如果x.equals(z)的放回值为TRUE.
  4. 一致性:对于任何非空引用x,y,那么多次调用x.equals(y)的放回值始终2一样(前提:对象上被比较的内容没被修改)
  5. 对于任何非空应用x,那么x.equals(null)的放回值始终为false。

在写实体类是必须重写equals方法

public class EqualsDemo{
    int id;
    public boolean equals(Object obj){
        if(obj==null){
            return false;
        }    
        if(this==obj){
            return true;
        }
        if(obj instanceof EqualsDemo){
            EqualsDemo e=(EqualsDemo)obj;
            return this.id=s.id;//比较的是内容,是具体的cr而定
        }
        return false;
    }
    
}

面试题:

shopping[] ss=new Shopping[]{s,new shopping()};
shopping[] ss1=new Shopping[]{s1,new shopping()};
System.out.println(Arrays.equals(ss,ss1));

注: 1))ss和ss1作比较时,是把数组中的对象作比较,在对象作比较时需要调用equals方法,

所以要求shopping对象要重写equals方法。

另外在扩展一下:list和set的contains方法:

  1. List的contains():只调用equals方法来判断结果
  2. Set的contains方法是先调用hashCode方法来判断,如果为真,就再调用对应的equals方法进行判断;如果hashCode方法比较的结果为false,就直接返回结果。

1.3 hashCode方法

public native int hashCode();是一个本地方法,采用hash算法将地址转换成唯一编码。

1)在重写equals方法时,须重写hashCode方法。

注:如果equals方法的值为TRUE,那么对象的hashCode必须一致 如果equals方法的值为false,那么对象的hashCode必须不一致 (因为hashCode方法返回的值是唯一标识当前对象的内容,而非它的地址)

2)当一个对象产生后,那么它的hashCode不能改变。hashCode通常情况下采用唯一标识(OID)。

II String

2.1 String的特性

  1. String类是不能被继承的,它被final修饰。
  2. String类内部的实现是char[](为什么不直接使用char[],干嘛还要用String: char[]值可随意的被改变,且字符串本身也是一种类型)
  3. 字符串的字面量也是String类型的实例(比如:String str="abc";//abc为字面量)。
  4. String类的设计原则是对象的内容不变。
  5. String类在实例化的过程中,如果他的实例都是字面量,且字面量的结果一致,那么系统会优化,让其在内存中的值存在一个空间中。 示例:
package com.csuinfosoft.stringDemo;
/**
 * 
 * @author 张坤楠
 * @date 下午3:22:58
 * String对象的比较,这里同一个对象的概念为内存地址,即使采用==比较对象,
 * 而非采用equals和hashCode,因为他们比的是内容。
 */
public class StringDemo {
	public static void main(String[] args){
		String str1="abc123";
		String str2="abc"+"123";
		final int i=123;
		String str3="abc"+i;
		//其中str1,str2,str3均为同一个对象。
		String str7="abc";
		String str8=str7+"123";//str1,和str8不是同一个对象,因为str7是变量,而非字面量。
		String str9=new String("abc123");//str1,str7,str8,str9这是个为不同的四个对象
		System.out.println(str1==str2);//true,比较的是内存地址
		System.out.println(str1==str3);//true,比较的是内存地址
		System.out.println(str2==str3);//true,比较的是内存地址
		System.out.println(str1.equals(str2));//true,比较的是内容
		
		System.out.println(str1==str8);//false,比较的是内存地址
		System.out.println(str1.equals(str8));//true,比较的是内容
		System.out.println(str1.hashCode()==str8.hashCode());//true,比较的是内容
		System.out.println(str1==str9);//false,比较的是内存地址
		System.out.println(str8==str9);//false,比较的是内存地址
		
	}
}

  1. String重写了toString(),equals(),hashCode()方法
  2. String API,如果String的方法的返回值为String类型时,那么就会产生一个新的对象,包括加号也会产生新对象。toString方法除外。
int length() 字符串长度
char charAt() 切割字符串,索引从0开始。
boolean equals(Object ) 比较两个字符串的内容是否相等
String trim() 去(前后)空白(空格,换行,制表符)的方法,

示例:

package com.zhongxin.util;
/**
 * 
 * @author 张坤楠
 *	去掉字符串的中间空白的示例
 */
public class DeleteSpaceUtil {
	public static String deleteSpace(String message){
		 String str = new String();
		 
		 String[] middle = message.split(" ");//没有必要提前去前后空白,
		 //因为middle的最后一个元素和第一个元素的长度与message前后空白无关
		 for(int i=0;i
String toLowerCase() 吧字符串大写转化成小写
String toUpperCase() 吧字符串大写转化成小写
String indexof(String str) 按照从左至右顺序查找str的位置,值查找第一个str就返回,找不到就返回-1.
String indexof(char c)
String indexof(String str,int loc ) 从loc位置开始,从左查找字符串的第一次出现的位置。
String ilastIdexof(String str ) 从字符串的微博查找字符串str的第一次出现的位置。
String subString(int i) 从i的位置开始到字符串结尾的字符串截取出来
String subString(int start,int end)   截取从start到end-1的位置的字符串。
String concat(String str)  连接字符串,和加号的作用一样
char[] tocharArray   吧字符串转化成字符串数组
new String(char[] c)  把字符数组转化成字符串

2.2 字符串和正则

  1. api boolean match(String regex) ;用于判断当前的字符串是否符合regex正则表达式。 String split (String regex) 根据regex将字符串切割成多个字串 String replaceAll(String regex ,String str); regex为要被替换的正则表达式,str为替换的内容。

分割字符串

        // 添加活动的限制条件
        if (StringUtils.isNotBlank(activity.getMerchantNatures())) {
            var natures = StringUtils.split(activity.getMerchantNatures(), ",");
            if (natures.length == 1) {
                lambda.eq(TMerMerchant::getNature, activity.getMerchantNatures());
            } else {
                lambda.in(TMerMerchant::getNature, natures);//(nature IN (?,?) 
            }
        }
  1. 正则表达式:用指定字符来限制当前字符串的内容。

正则的语法:

普遍的字符串 ”abc“

  • 【】 代表当前位置可以出现的字符
  • {}代表当前字符串可以出现的次数:示例,手机号码,num.matches("[1]{1}[3458]{1}[0-9]{9}");

注:【0-9】- 从起始位置到结束之间的字符串多可取。

  • ^ 字符串的起始位置,行的开头
  • $字符串的结束位置,行的结尾

示例:用户名:字母,数字,下划线,长度为6,20.

^[0-9a-zA-Z_]{6,20}$或者^\\w{6,20}$ 其中\是用于转换的

{start,end} 代表可以出现start到end之间数字的次数

  • \d 代表【0-9】
  • \D 代表非数字
  • \w 代表【a-zA-Z0-9_】 字符
  • \W 代表【^\w】

2.3 StringBuilder,StringBuffer

  1. 特点:都是被final修饰,不能被继承。

都是动态字符序列(采用动态数组的算法,来实现动态存储数据方式,完成字符串的动态存储,采用变长数组存储。)

内存对象内容是可变的,说明他们是一个可变的字符序列。

StringBuilderAPI

  • StringBuilder append(String) 向原字符串追加新的字符串 - StringBuilder insert(int index,String str) 在index位置向原字符串插入新的字符串str,index从0开始
  • StringBuilder delete(int index,int end) 删除start到end的字符串,小标不包含end,即到end-1
  1. 应用场景:有大量的字符串操作
  2. StringStringBuilderStringBuffer之间的转化
  • StringBuilder,StringBufferString的转化:调用toString()方法
  • String转化到 StringBuilder,StringBuffer:使用对应的构造器,比如:new StringBuilder(String str);
//注:java优化String代码的示例:
public class StringJavaDemo{
    public static void main(String[] args){
            String str1="a";
            String str2="b";
            String str3=str1+str2;//ava会优化此代码,相当于Str3=new StringBuilder().appned(str1).append(str2).toString();
            
    }
}

  1. StringBuilder,StringBuffer之间的关系
  • 相同点:

内部是char[],是可变的字符序列

API大致相同

  • 不相同点:

StringBuffer,是java早期引入的,线程安全,速度慢

StringBuilder,是java 5.0引入的,非线程安全,速度快

String采用定长数组,StringBuilder,StringBuffer采用变长数组