一、String类的重要性
在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字符串应用又非常广泛,因此Java语言专门提供了String类。
- 与C语言不同,C语言中字符串是以"\0"结尾的,也就是说这是它的结束标志
- 但Java中并不以"\0"结尾,有它本身的判断结束方法
二.常用方法
1 字符串构造
- 1.使用常量串构造
- 2.直接newString对象
- 3.使用字符数组进行构造
String string1="hello";
String string2=new String("world");
char[] value={'a','b','c'};
String string3=new String(value);
public static void main(String[] args) {
// s1和s2引用的是不同对象 s1和s3引用的是同一对象
String s1 = new String("hello");
String s2 = new String("world");
String s3 = s1;
System.out.println(s1.length()); // 获取字符串长度---输出5
System.out.println(s1.isEmpty()); // 如果字符串长度为0,返回true,否则返回false
}
2. 在Java中“”引起来的也是String类型对象。
2 String对象的比较
(1)==比较是否引用同一个对象
public class Test {
public static void main(String[] args) {
String string1="hello";
String string2=new String("world");
char[] value={'a','b','c'};
String string3=new String(value);
String string4=string1;
String string5="hello";
System.out.println(string1==string4);
System.out.println(string1==string2);
}
}
(2)boolean equals
(3)int compareTo(String s)
public static void main(String[] args) {
String string1=new String("world");
String string2=new String("abcdef");
String string3=new String("abcdef");
String string4=new String("abcdefg");
System.out.println(string2.compareTo(string1));
System.out.println(string2.compareTo(string4));
System.out.println(string2.compareTo(string3));
System.out.println(string1.compareTo(string3));
}
(4)int compareToIgnoreCase(String str)
public static void main(String[] args) {
String string1=new String("Abcdef");
String string3=new String("abcdef");
System.out.println(string1.compareTo(string2));
System.out.println(string1.compareToIgnoreCase(string2));
}
3 字符串查找
方法 | 功能 |
char charAt(int index) | 返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常 |
int indexOf(int ch) | 返回ch第一次出现的位置,没有返回-1 |
int indexOf(int ch, int fromlndex) | 从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 lastindexOf(int ch, int fromindex) | 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1 |
int lastindexOf(String str) | 从后往前找,返回str第一次出现的位置,没有返回-1 |
int lastindexOf(String str, int fromindex) | 从fromindex位置开始找,从后往前找str第一次出现的位置,没有返回-1 |
(1)char charAt(int index)
public static void main(String[] args) {
String s1="hello";
char c=s1.charAt(0);
System.out.println(c);
}
(2)int indexOf(int ch)+int indexOf(int ch, int fromlndex)
public static void main(String[] args) {
String s1="hello";
int index=s1.indexOf('l');
int index2=s1.indexOf('l',3);
System.out.println(index);
System.out.println(index2);
}
(3)int indexOf(String str)
public static void main(String[] args) {
String s1="hello";
int index3=s1.indexOf("ll");
System.out.println(index3);
}
(4)int indexOf(String str, int fromindex)
public static void main(String[] args) {
String s1="hello";
int index3=s1.indexOf("ll",3);
System.out.println(index3);
}
tip:后四个方法与前四个基本相同,不再演示
4 转化
(1)数值和字符串转化
该方法是一个静态方法,用类名.方法名
String s1=String.valueOf(1234);
String s2=String.valueOf(12.34);
int i=Integer.parseInt(s1);
double d=Double.parseDouble(s2);
(2)大小写转换
public static void main(String[] args) {
String s1="hello";
String s2=s1.toUpperCase();
System.out.println(s2);
}
public static void main(String[] args) {
String s1="hello";
String s2=s1.toUpperCase();
String s3=s2.toLowerCase();
System.out.println(s3);
}
(3)字符串转数组
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);
}
(4)格式化
public static void main(String[] args) {
String S=String.format("%d-%d-%d",2024,9,27);
System.out.println(S);
}
5 字符串替换
使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:
代码演示:
public static void main(String[] args) {
String s="aaaaaaaaaabbbbbbbbbbbb";
String S1=s.replace('a','k');
String S2=s.replaceFirst("a","k");
System.out.println(S1);
System.out.println(S2);
}
6 字符串拆分
方法 | 功能 |
String[] split(String regex) | 将字符串全部拆分 |
String[]split(String regex, int limit) | 将字符串以指定的格式,拆分为limit组 |
(1)String[] split(String regex)
public static void main(String[] args) {
String s1="name=sherry&age=20";
String[] strings=s1.split("&");
for (String s:strings) {
System.out.println(s);
}
}
(2)String[]split(String regex, int limit)
public static void main(String[] args) {
String s1="name=sherry&age=20";
String s2="hello world I love you";
String[] strings=s1.split("&");
String[] strings2=s2.split(" ",2);
for (String s:strings2) {
System.out.println(s);
}
}
String str = "192.168.1.1" ;
String[] result = str.split("\\.") ;
for(String s: result) {
System.out.println(s);
}
public static void main(String[] args) {
String s1="name=sherry&age=20";
String[] strings=s1.split("&|=");
for (String S:strings) {
System.out.println(S);
}
}
(3)多次拆分
public static void main(String[] args) {
String s1="name=sherry&age=20";
String[] strings=s1.split("&");
for (int i = 0; i < strings.length; i++) {
String[] strings2=strings[i].split("=");
for (String S:strings2) {
System.out.println(S);
}
}
}
7 字符串截取
方法 | 功能 |
String substring(int beginindex) | 从指定索引截取到结尾 |
String substring(int beginindex, int endlndex) | 截取部分内容 |
代码示例: 观察字符串截取
public static void main(String[] args) {
String s="abcdefg";
String sub=s.substring(2,5);
System.out.println(sub);
}
注意事项:
8 其他操作方法
String trim()
public static void main(String[] args) {
String s=" a b cde f ";
String ss=s.trim();
System.out.println(ss);
}
9 字符串的不可变性
- 1. String类被final修饰,表明该类不能被继承
- 2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。
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 中 .那如果想要修改字符串中内容,该如何操作呢?
10 字符串修改
public static void main(String[] args) {
String s = "hello";
s += " world";
System.out.println(s); // 输出:hello world
}
public static void main(String[] args) {
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("hello");
stringBuilder.append(" world");
String s=stringBuilder.toString();
System.out.println(s);
}
public static void main13(String[] args) {
String s1="hello";
s1+=" world";
System.out.println(s1);
}
但是string+=这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。
可以看待在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder。
三. StringBuilder和StringBuffer
1 StringBuilder的介绍
方法 | 说明 |
StringBuff append(Stringstr) | 在尾部追加,相当于String的+=,可以追加:boolean、char、char[l.double、float、int、long、Object、String、StringBuff的变量 |
char charAt(int index) | 获取index位置的字符 |
int length() | 获取字符串的长度 |
int capacity() | 获取底层保存字符串空间总的大小 |
void ensureCapacity(intmininmumCapacity) | 扩容 |
void setCharAt(int index,char ch) | 将index位置的字符设置为ch |
int indexOf(String str) | 返回str第一次出现的位置 |
int indexOf(String str, intfromIndex) | 从fromIndex位置开始查找str第一次出现的位置 |
int lastindexOf(String str) | 返回最后一次出现stt的位置 |
int lastIndexOf(String str,int fromIndex) | 从fromtindex位置开始找str最后一次出现的位置 |
StringBuff insert(intoffset, String str) | 在offset位置插入:八种基类类型 & String类型 & Object类型数据 |
StringBufferdeleteCharAt(int index) | 删除index位置字符 |
StringBuffer delete(intstart, int end) | 删除[start, end)区间内的字符 |
StringBuffer replace(intstart, int end, String str) | 将[start,end)位置的字符替换为str |
String substring(int start) | 从start开始一直到未尾的字符以String的方式返回 |
String substring(intstart, int end) | 将[start,end)范围内的字符以String的方式返回 |
StringBuffer reverse() | 反转字符串 |
String toString() | 将所有字符按照String的方式返回 |
注意: String 和 StringBuilder 类不能直接转换。如果要想互相转换,可以采用如下原则 :
- String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
- StringBuilder变为String: 调用toString()方法。
- String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
- StringBuffer与StringBuilder大部分功能是相似的
- StringBuffer采用同步处理,,一般用于多线程,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
String str = new String ( "ab" ); // 会创建多少个对象String str = new String ( "a" ) + new String ( "b" ); // 会创建多少个对象
四. String类oj
1. 第一个只出现一次的字符
class Solution {
public int firstUniqChar(String s) {
int[] count=new int[26];
int pos=-1;
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
count[ch-'a']++;
}
for(int j=0;j<s.length();j++){
int k=s.charAt(j)-'a';
if(count[k]==1){
pos=j;
break;
}
}
return pos;
}
}
2. 最后一个单词的长度
采用split方法
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String string=in.nextLine();
String[] s=string.split(" ");
String ss=s[s.length-1];
System.out.println(ss.length());
}
}
不采用spli方法
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String string=in.nextLine();
int count=0;
for(int i=string.length()-1;i>=0;i--){
if(string.charAt(i)==' '){
break;
}
count++;
}
System.out.println(count);
}
}
3. 检测字符串是否为回文
class Solution {
public static boolean isLegal(char ch){
boolean flag=false;
if(ch>='a'&&ch<='z'){
flag=true;
}else if(ch>='0'&&ch<='9'){
flag=true;
}
return flag;
}
public boolean isPalindrome(String s) {
String string=s.toLowerCase();
int left=0;
int right=string.length()-1;
while(left<right){
while(left<right && (isLegal(string.charAt(left))==false)){
left++;
}
while(left<right && (isLegal(string.charAt(right))==false)){
right--;
}
if(string.charAt(left)==string.charAt(right)){
left++;
right--;
}else{
return false;
}
}
return true;
}
}
Tip:在这个过程中,我了解了判断是不是数字和字母,Java中有专门的方法
即:Character.isDigit()和Character.isLetter()
4.下列程序运行结果:
public class Example{
String str = new String("good");
char[ ] ch = { 'a' , 'b' , 'c' };
public static void main(String args[]){
Example ex = new Example();
ex.change(ex.str,ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str,char ch[ ]){
str = "test ok";
ch[0] = 'g';
}
}
good and gbc
主要考察传引用会发生的问题。分为两种情况:
- 通过引用,修改原来的内存
- 通过引用,修改当前引用的指向