文章目录
1.字符串的处理
1.1 字符串的基本操作
前言
String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。大小写映射基于 Character 类指定的 Unicode 标准版。
1,定义字符串(最常使用的创建方式)
String str = "Hello Java";
2,String转int
int i = Integer.parseInt("12");
System.out.println(i);
这里要考虑一个问题:需要判断字符串中的数据 是否是int类型
如果我们,输入一个String str="苹果";
它还可以转成int
类型,能成功输出吗?
很显然,是不行的!于是我们在企业实战项目中就需要判断,前端返回给我的字符串的里面是不是int类型!
解决方法:正则表达式判断
public static void main(String[] args) {
String str="苹果";
// 判断是否是int类型
Pattern pattern = Pattern.compile("[0-9]*");
Matcher isNum = pattern.matcher(str);
if(! isNum.matches() ){
System.out.println("不是int类型");
}else{
int i = Integer.parseInt(str);
System.out.println(i);
}
}
假如说,我们对于精度有要求,我们可不可以转化成为精度更高的float,double类型的呢?当让可以,以此类推
public static void main(String[] args) {
float i = Float.parseFloat("10.1");
System.out.println(i);
double v = Double.parseDouble("10.00");
System.out.println(v);
}
3,int转String
有三种方式
- String.valueOf(i)
- Integer.toString(i)
- “”+i
public static void main(String[] args) {
int i=10;
String s1 = String.valueOf(i);
String s2 = Integer.toString(i);
String s3 = ""+i;
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
4,拼接字符串
常用的方法有两种
- concat()方法
格式:str1.concat(str2);
- +号拼接
格式:str1+str2
public static void main(String[] args) {
String s1="aa";
String s2="bb";
String concat = s1.concat(s2);
System.out.println(concat);
System.out.println(s1+s2);
}
5,字符串转大小写
试想一下,假如别人给你发了一大段的英文子段,我们现在对它做一些处理
String str="sfdasdfKKJJNKJSSDaassefJJJWFDASNsnfnksjfs";
转大写
String s3 = str.toUpperCase();
转小写
String s4 = str.toLowerCase();
但是,我发现了另外的两个东西
str.toUpperCase(Locale.ROOT);
str.toLowerCase(Locale.ROOT);
测试一下:
public static void main(String[] args) {
String str="sfdasdfKKJJNKJSSDaassefJJJWFDASNsnfnksjfs";
String s1 = str.toUpperCase(Locale.ROOT);
String s2 = str.toLowerCase(Locale.ROOT);
String s3 = str.toUpperCase();
String s4 = str.toLowerCase();
System.out.println("toUpperCase(Locale.ROOT) 大写:"+s1);
System.out.println("toLowerCase(Locale.ROOT) 小写:"+s2);
System.out.println("str.toUpperCase()大写:"+s3);
System.out.println("str.toLowerCase()小写:"+s4);
}
感觉差不多啊!没有什么区别哎。再去找找博客。。。
找到了
我看了一下哈,只要各位小伙伴不出国,基本上没啥问题哈!主要问题是各个国家的字符标准不一定和国籍标准一致的,所以在其他的国家会出现字符转换的错误。
所以啊,建议小伙伴们用国际标准
String s1 = str.toUpperCase(Locale.ROOT);
String s2 = str.toLowerCase(Locale.ROOT);
以绝后患!!!
6,去除字符串中的空格
trim()
现在我们创建一个字符串
String str=" sfdasdfKKJJNKJS DaassefJJ WFDASNsnfnksjfs ";
字符串中有着很多的空格,我们想要去除。
public static void main(String[] args) {
String str=" sfdasdfKKJJNKJS DaassefJJ WFDASNsnfnksjfs ";
String trim = str.trim();
System.out.println("处理前:"+str);
System.out.println("处理后:"+trim);
}
发现trim()
方法只能处理头部和尾部的空格,中间的不行
我们尝试用新的方法replace()
方法;
public static void main(String[] args) {
String str = " sfdasdfKKJJNKJS DaassefJJ WFDASNsnfnksjfs ";
String trim = str.trim();
System.out.println("处理前:" + str);
System.out.println("处理后:" + trim);
String replace = str.replace(" ", "");
System.out.println("replace处理后:"+replace);
}
就是我想要的結果。
那我们就开始解析一下replace()
方法吧
上面的使用的,是将空值来代替空格
str.replace(" ", "");
格式:replace("要被替换的部分","填充进去的部分");
举个栗子:
public static void main(String[] args) {
String str="123456789";
String replace = str.replace("5", "0");
System.out.println("replace处理后:"+replace);
}
5
被替换掉了,取而代之的是0
;
7,截取部分字符串
截取字符串JDK API中提供了有两种方法
1.定义开始位置,从开始位置截取到字符串尾部
substring(int beginIndex)
2.定义开始位置,定义结束位置,截取开始到结束位置的字符串片段
subSequence(int beginIndex, int endIndex)
实例演示
public static void main(String[] args) {
String s1="aaaBBBcccDDD";
String substring1 = s1.substring(2);
String substring2 = s1.substring(2, 6);
System.out.println(substring1);
System.out.println(substring2);
}
8,分割字符串
分割字符串是很重要的一个知识点,试想一下业务场景,前端给你返回了一个长长的字符串里面全是人名,需要你插入数据库。
String s1="李白、杜甫、李商隐、杜牧、元缜、白居易";
我们这个时候可以使用split()
方法
public static void main(String[] args) {
String s1="李白、杜甫、李商隐、杜牧、元缜、白居易";
String[] split = s1.split("、");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
其实split()
方法是可以配合着正则表达式
来做的,不过基础阶段,没有复杂的业务场景就不考虑了
9,字符串的替换
在上面的去除字符串中的空格中,我们使用到了replace()
方法,其实replace()
的真实作用是替代,而非删除
JDK API中有着三种方法实现字符串替换
replace();
replaceAll();
replaceFirst();
举个栗子
public static void main(String[] args) {
String s1="李白、杜甫、李商隐、杜牧、元缜、白居易、杜甫";
String r1 = s1.replace("杜甫", "屈原");
String r2 = s1.replaceAll("杜甫", "屈原");
String r3 = s1.replaceFirst("杜甫", "屈原");
System.out.println(r1);
System.out.println(r2);
System.out.println(r3);
}
可以看到replace
和replaceAll
都是全部替换
而replaceFirst()
是单个替换,且替换的是首个出现的
那么,replace()
和replaceAll()
的区别又是什么呢?
答案:replacAll()
可以使用正则表达式
,在使用的时候要注意. [ *
的字符,一不小心就触发正则表达式
,初学者还是用replace()
就可以了,基本上可以满足日常需求了
10,字符串的比较
比较的方法有以下几种
equals
equalsIgnoreCase
compareTo
compareToIgnoreCase
下面来解析这几种方法:
1,equals
public static void main(String[] args) {
String s1="BBB";
String s2="bbb";
boolean equals = s1.equals(s2);
System.out.println(equals);
}
说起equals
就不得不说equals
和==
之间的区别了
我们来测试一下:
public static void main(String[] args) {
String s1="aa";
String s2="aa";
System.out.println(s1.equals(s2));
System.out.println(s1==s2);
}
public static void main(String[] args) {
String s1 = new String("aa");
String s2 = new String("aa");
System.out.println(s1.equals(s2));
System.out.println(s1==s2);
}
从以上的两个测试中可以看到:
- 对于
String
类型的字符串而言,equals
比较的是字符串的内容。 - 而当我们使用
new String("aa')
时,创建出来的String
对象的在堆中的存储地址是不同的,于是System.out.println(s1==s2);
输出的结果是false
,可以知道,==
比较的是字符串对象的地址。
那么,问题又来了,String str="aa"
和String str = new String("aa");
这两种创建字符串的形式有什么区别?
答案:1:当我们采用String str="aa"
这种创建方式时,创建的字符串会存储到常量池中,
String s1="aa";
String s2="aa";
"aa"
在程序编译的时候被JVM加入到常量池中,并将其在常量池中的地址赋值给s1;
当我们再次创建s2时,JVM先在常量池中查找是否存在"aa"
常量,s1已经在在常量池里创建过"aa"
了,JVM也想偷个懒嘛,直接把s1的地址赋值给s2,因此str和str1的地址是一样的。
2. 当我们使用String str = new String("aa");
,创建出来的对象是存储来堆内存中的,每次创建出来的对象的地址都是不一样的。
扩展
==
对于基本类型来说,==
比较的是值是否相等
对于引用类型来说,==
比较的是两者在内存中存放的地址(堆内存地址)
equals
引用类型:
默认情况下,对比它们的地址是否相等;
如果equals()方法被重写,则根据重写过程来比较
2,equalsIgnoreCase
作用:将此 String 与另一个 String 比较,不考虑大小写。
public static void main(String[] args) {
String s1 = new String("aa");
String s2 = new String("AA");
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));
}
equals
在比较两个字符串的时候是考虑大小写的equalsIgnoreCase
在比较两个字符串的时候是不考虑大小写
3,compareTo
作用:按字典顺序比较两个字符串。
比较的依据:该比较基于字符串中各个字符的 Unicode 值。按字典顺序将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。
结果返回
- 如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。
- 如果按字典顺序此 String对象位于参数字符串之后,则比较结果为一个正整数。
- 如果这两个字符串相等,则结果为 0;
public static void main(String[] args) {
String a= new String("a");
String b = new String("b");
String s1= new String("a");
System.out.println(a.compareTo(b));
System.out.println(b.compareTo(a));
System.out.println(a.compareTo(s1));
}
a.compareTo(b)
a在b之前,返回-1(b.compareTo(a))
b在a之后,返回1a.compareTo(s1)
a和s1相等,返回0
4,compareToIgnoreCase
**作用:**按字典顺序比较两个字符串,不考虑大小写。
public static void main(String[] args) {
String a= new String("a");
String s1= new String("a");
String b = new String("B");
System.out.println(a.compareToIgnoreCase(b));
System.out.println(b.compareToIgnoreCase(a));
System.out.println(a.compareToIgnoreCase(s1));
}
将new String("b");
修改为new String("B");
结果并没有改变
常用的一些方法就在这里了,还有一些JDK API的方法我放在下面了
11,JDK String 方法大全
char | charAt(int index) 返回指定索引处的 char 值。 |
---|---|
int | codePointAt(int index) 返回指定索引处的字符(Unicode 代码点)。 |
int | codePointBefore(int index) 返回指定索引之前的字符(Unicode 代码点)。 |
int | codePointCount(int beginIndex, int endIndex) 返回此 String 的指定文本范围中的 Unicode 代码点数。 |
int | compareTo(String anotherString) 按字典顺序比较两个字符串。 |
int | compareToIgnoreCase(String str) 按字典顺序比较两个字符串,不考虑大小写。 |
String | concat(String str) 将指定字符串连接到此字符串的结尾。 |
boolean | contains(CharSequence s) 当且仅当此字符串包含指定的 char 值序列时,返回 true。 |
boolean | contentEquals(CharSequence cs) 将此字符串与指定的 CharSequence 比较。 |
boolean | contentEquals(StringBuffer sb) 将此字符串与指定的 StringBuffer 比较。 |
static String | copyValueOf(char data) 返回指定数组中表示该字符序列的 String。 |
static String | copyValueOf(char data, int offset, int count) 返回指定数组中表示该字符序列的 String。 |
boolean | endsWith(String suffix) 测试此字符串是否以指定的后缀结束。 |
boolean | equals(Object anObject) 将此字符串与指定的对象比较。 |
boolean | equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。 |
static String | format(Locale l, String format, Object… args) 使用指定的语言环境、格式字符串和参数返回一个格式化字符串。 |
static String | format(String format, Object… args) 使用指定的格式字符串和参数返回一个格式化字符串。 |
byte | getBytes() 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 |
byte | getBytes(Charset charset) 使用给定的 charset将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。 |
void | getBytes(int srcBegin, int srcEnd, byte dst, int dstBegin) 已过时。 该方法无法将字符正确转换为字节。从 JDK 1.1 起,完成该转换的首选方法是通过 getBytes() 方法,该方法使用平台的默认字符集。 |
byte | getBytes(String charsetName) 使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 |
void | getChars(int srcBegin, int srcEnd, char dst, int dstBegin) 将字符从此字符串复制到目标字符数组。 |
int | hashCode() 返回此字符串的哈希码。 |
int | indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引。 |
int | indexOf(int ch,int fromIndex) 返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。 |
int | indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引。 |
int | indexOf(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 |
String | intern() 返回字符串对象的规范化表示形式。 |
boolean | isEmpty() 当且仅当 length() 为 0 时返回 true。 |
int | lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出现处的索引。 |
int | lastIndexOf(int ch, int fromIndex) 返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。 |
int | lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引。 |
int | lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 |
int | length() 返回此字符串的长度。 |
boolean | matches(String regex) 告知此字符串是否匹配给定的正则表达式 |
int | offsetByCodePoints(int index, int codePointOffset) 返回此 String 中从给定的 index 处偏移 codePointOffset 个代码点的索引。 |
boolean | regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) 测试两个字符串区域是否相等。 |
boolean | regionMatches(int toffset, String other, int ooffset, int len) 测试两个字符串区域是否相等。 |
String | replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 |
String | replace(CharSequence target, CharSequence replacement) 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。 |
String | replaceAll(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 |
String | replaceFirst(String regex, String replacement) 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。 |
String | split(String regex) 根据给定正则表达式的匹配拆分此字符串。 |
String | split(String regex, int limit) 根据匹配给定的正则表达式来拆分此字符串。 |
boolean | startsWith(String prefix) 测试此字符串是否以指定的前缀开始。 |
boolean | startsWith(String prefix, int toffset) 测试此字符串从指定索引开始的子字符串是否以指定前缀开始。 |
CharSequence | subSequence(int beginIndex, int endIndex) 返回一个新的字符序列,它是此序列的一个子序列。 |
String | substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串。 |
String | substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串。 |
char | toCharArray() 将此字符串转换为一个新的字符数组。 |
String | toLowerCaseto() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 |
String | toLowerCasetoLowerCase(Locale locale) 使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。 |
String | toString() 返回此对象本身(它已经是一个字符串!)。 |
String | toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 |
String | toUpperCasetoUpperCase(Locale locale) 使用给定 Locale 的规则将此 String 中的所有字符都转换为大写。 |
String | trim() 返回字符串的副本,忽略前导空白和尾部空白。 |
static String | valueOf(boolean b) 返回 boolean 参数的字符串表示形式。 |
static String | valueOf(char c) 返回 char 参数的字符串表示形式。 |
static String | valueOf(char data) 返回 char 数组参数的字符串表示形式。 |
static String | valueOf(char data, int offset, int count) 返回 char 数组参数的特定子数组的字符串表示形式。 |
static String | valueOf(double d) 返回 double 参数的字符串表示形式。 |
static String | valueOf(float f) 返回 float 参数的字符串表示形式。 |
static String | valueOf(int i) 返回 int 参数的字符串表示形式。 |
static String | valueOf(long l) 返回 long 参数的字符串表示形式。 |
static String | valueOf(Object obj) 返回 Object 参数的字符串表示形式。 |
1.2 StringBuffer和StringBuilder
StringBuffer api原文介绍:
StringBuffer
线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
String字符串的缺点:
String字符串
在创建之后,长度不可变,如果对它进行修改,会产生新的对象。
于是
StringBuffer
和StringBuilder
依此而生。
String,StringBuffer和StringBuilder的比较
相同点:
- 相对于String而言,StringBuffer和StringBuilder类的对象都是可编辑的,并且不会产生新的对象。
- 相对于String而言,StringBuffer和StringBuilder对字符串增伤改的时候性能要优于String
- 相对于String而言,StringBuffer和StringBuilder可对字符串编辑,所以,编译器不可以把字符串设为共享的。
StringBuffer和StringBuilder的差异:
1、StringBuffer是线程安全的,StringBuilder不是线程安全的,
可以看到所有的方法前都有synchronized
修饰。
而StringBuiider
却是没有。
2、效率方面,StringBuilder>StringBuffer>String
为什么StringBuilder这么快?
答案:因为StringBuilder是单线程的,没有synchronized
约束,StringBuffer
就是为了多线程而设计的,这样可以防止多个线程同时操作同一个对象,也就是线程安全,当多个线程访问加锁的方法时,每次只有一个线程获得锁,其他线程必须等待该线程释放锁,再由下一个线程获得锁,才允许执行该方法,加锁会带来性能上的损耗。
而相对于String
我们看一下源码
String被final
修饰,不可变,所以我们想要对String字符串进行操作时,构建一个新的字符串对象,需要做申请内存,开辟空间等操作。
StringBuilder和StringBuffer该怎么选?
先确定是否使用多线程,如果只是用单线程,就用StringBuilder;多线程,就是用StringBuffer。
以StringBuffer举例实战:
1、创建
StringBuffer stringBuffer = new StringBuffer();
2、增
stringBuffer.append("hello world");
3、删
// 删除第2位,第3位的字符(注意)
stringBuffer.delete(2,4);
// 删除第5位字符
stringBuffer.deleteCharAt(5);
// 删除第末尾位字符
stringBuffer.deleteCharAt(stringBuffer.length()-1);
4、插入
stringBuffer.insert(7,"java 1.8");
5,修改(或者说替换)
stringBuffer.replace(6,11,"java");