String:不可变,每次变更都会产生新的对象,因此有性能问题;
StringBuffer:解决了可变问题,线程安全;
StringBuilder:解决了可变问题,非线程安全;
子串是指原字符串的一部分,一整块;子序列指的是字符串在原字符串中每个字符顺序相同。
String:
lang,不需要import
常量,创建之后永不可变。因此相同内容可以共享使用,节省内存。
效果上是char[]型数组,但底层原理是byte[]字节数组。
print的不是地址
记忆:只要改变字符串就会返回一个String
之前前面char[],JDK10之后是byte[]
创建字符串的常见3+1种方式:
三种构造方法,一种直接创建:
public String();//创建一个空白字符串,不含有任何内容
public String(char[] array);//根据字符数组的内容,来创建对应的字符串
public String(byte[] array);//根据字节数组的内容,来创建对应的字符串
//byte 传入数据保存是英文字母(猜)
String str = "Hello";//直接创建
字符串的常量值:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-orj2ijMe-1610606423379)(H:\MyLession\self.study\pic\01-字符串的常量池.png)]
String的相关方法:
public int length();//返回字符串当中含有的字符个数,是方法, array.length是没有括号的,是属性
//注意字符串可以使用+号拼接
public String concat(String str);//将当前字符串和参数字符串拼接为新String返回
str1str2 = str1.concat(str2);
str1str2 = str1+str2;
public char charAt(int index);//获取指定索引的单个字符start at 0
public int indexOf(String str);//查找参数字符串 首次 出现的位置,没有返回 -1
public boolean matches(String regex) {}//匹配,可以是正则表达式
子字符串:(substring)完整的单词,s小写
public String substring(int index);//截取从该位置到末尾的字符串
public String substring(int begin, int end);//左闭右开截取字符串
字符串转换:
public char[] toCharArray();//拆分为字符数组返回
public byte[] getBytes();//获得字符串底层的字节数组
public String replace(CharSequence oldString, CharSequence newString);//CharaSquence是一个interface,表示可以接受字符串类型。将所有oldString替换成新的
char to String:
//1.效率最高得到一种方法
String s = String.valueOf('c');
//2.将字符串数组转化为字符串
String s = String.valueOf(new char[] {'G','e','o','o','o'});
//3.用 Character 的 toString(char) 方法 ==> 实际上还是调用了String.valueOf(char)
String s = Character.toString('c');
基本类型字符串互转:
Integer.parseInt();
Double.paeseDouble();
//等等 包装类.parse包装类();
String s = number + "";//原理StringBuilder.append
字符串分割:
public String[] split(String regex);//按照参数的规则,将字符串切分成为若干部分
regex: regular expression 正则表达式
字符串例子:
数组转字符串
public static String getdf(int[] array) {
String str = "[";
for (int i = 0; i < array.length; i++) {
if (i == array.length - 1) {
str += "zly" + array[i] + "]";
} else {
str += "zly" + array[i] + "@";
}
}
return str;
}
统计输入字符串中所有字符的类型,大小写数字和其它。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String input = sc.next(); // 获取键盘输入的一个字符串
int countUpper = 0; // 大写字母
int countLower = 0; // 小写字母
int countNumber = 0; // 数字
int countOther = 0; // 其他字符
char[] charArray = input.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char ch = charArray[i]; // 当前单个字符
if ('A' <= ch && ch <= 'Z') {
countUpper++;
} else if ('a' <= ch && ch <= 'z') {
countLower++;
} else if ('0' <= ch && ch <= '9') {
countNumber++;
} else {
countOther++;
}
}
System.out.println("大写字母有:" + countUpper);
System.out.println("小写字母有:" + countLower);
System.out.println("数字有:" + countNumber);
System.out.println("其他字符有:" + countOther);
StringBuilder类:
-
public StringBuilder()
:构造一个空的StringBuilder容器。 -
public StringBuilder() { super(16); }
-
public StringBuilder(String str)
:构造一个StringBuilder容器,并将字符串添加进去。 -
public StringBuilder(String str) { super(str.length() + 16); append(str); }
public class Demo02StringBuilder {
public static void main(String[] args) {
//创建对象
StringBuilder builder = new StringBuilder();
//public StringBuilder append(任意类型)
StringBuilder builder2 = builder.append("hello");
//对比一下
System.out.println("builder:"+builder);
System.out.println("builder2:"+builder2);
System.out.println(builder == builder2); //true,重写了toString方法
// 可以添加,任何类型
builder.append("hello");
builder.append("world");
builder.append(true);//==传入true的一个String
builder.append(100);
// 在我们开发中,会遇到调用一个方法后,返回一个对象的情况。然后使用返回的对象继续调用方法。
// 这种时候,我们就可以把代码现在一起,如append方法一样,代码如下
//链式编程
builder.append("hello").append("world").append(true).append(100);
System.out.println("builder:"+builder);
}
}
StringBuffer类:
区别:线程安全
String算法:
KMP算法(看毛片算法)
public class KMPTest(){
public static void main(String[] args) {
String text = new String("abaabaabbabaaabaabbabaab");
String str = "abaabbabaab";
int index = KMPString(text, str);
System.out.println(index);
}
public static int KMPString(String text, String str) {
int numOfMatch = 0;
int[] arr = getMatchNumArr(str);
for (int i = 0; i < text.length(); i++) {
while (numOfMatch > 0 && str.charAt(numOfMatch) != text.charAt(i)) {
numOfMatch = arr[numOfMatch - 1];
}
if (str.charAt(numOfMatch) == text.charAt(i)) {
numOfMatch++;
}
if (numOfMatch == str.length()) {
return i-str.length()+1;
}
}
return -1;
}
public static int[] getMatchNumArr(String targetStr) {
int maxSubstrIndex = 0;
int[] MatchNumArr = new int[targetStr.length()];
for (int i = 1; i < targetStr.length(); i++) {//1开始
while (maxSubstrIndex > 0 && targetStr.charAt(maxSubstrIndex)
!= targetStr.charAt(i)) {
maxSubstrIndex = MatchNumArr[maxSubstrIndex - 1];
}
if (targetStr.charAt(maxSubstrIndex) == targetStr.charAt(i)) {
maxSubstrIndex++;
}
MatchNumArr[i] = maxSubstrIndex;
}
return MatchNumArr;
}
}
Java中的strstr
public int strStr(String ss, String s) {
char[] source = ss.toCharArray();
char[] target = s.toCharArray();
if (0 == source.length) {
return (target.length == 0 ? 0 : -1);
}
if (target.length == 0) {
return 0;
}
char first = target[0];
int max = (source.length - target.length);
for (int i = 0; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + target.length - 1;
for (int k = 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i;
}
}
}
return -1;
}
KMP
public static int getIndexOf(String s, String m) {
if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
return -1;
}
char[] str = s.toCharArray();
char[] match = m.toCharArray();
int x = 0; // str中当前比对到的位置
int y = 0; // match中当前比对到的位置
// M M <= N O(M)
int[] next = getNextArray(match); // next[i] match中i之前的字符串match[0..i-1]
// O(N)
while (x < str.length && y < match.length) {
if (str[x] == match[y]) {
x++;
y++;
} else if (next[y] == -1) { // y == 0
x++;
} else {
y = next[y];
}
}
return y == match.length ? x - y : -1;
}
// M O(M)
public static int[] getNextArray(char[] match) {
if (match.length == 1) {
return new int[] { -1 };
}
int[] next = new int[match.length];
next[0] = -1;
next[1] = 0;
int i = 2;
// cn代表,cn位置的字符,是当前和i-1位置比较的字符
int cn = 0;
while (i < next.length) {
if (match[i - 1] == match[cn]) { // 跳出来的时候
next[i++] = ++cn;
} else if (cn > 0) {
//一直找匹配
cn = next[cn];
} else {
next[i++] = 0;
}
}
return next;
}
Sunday
public static int strStr(String text, String match) {
if (text == null)
return -1;
if (match == null || match.length() == 0)
return 0;
if (text.length() < match.length())
return -1;
int len = text.length();
int slen = match.length();
int k = 0;
int[] shift = new int[256];
for (char c : match.toCharArray())
shift[c] = slen - k++;
int i = 0;
while (i + slen <= len) {
if (iequals(text, i, match))
return i;
else {
if (i + slen < len && shift[text.charAt(i + slen)] != 0)
i += shift[text.charAt(i + slen)];
else
i += slen;
}
}
return -1;
}
//避免使用substring取子串,生成过多的String对象
private static boolean iequals(String str1, int offset, String str2) {
for (int i = 0; i < str2.length(); i++)
if (str2.charAt(i) != str1.charAt(i + offset))
return false;
return true;
}