目录
--------------------------------
--------------------------------
二、将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反 转为”abfedcg”
三、获取一个字符串在另一个字符串中出现的次数。 比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数
--------------------------------
2. 为什么对于安全性敏感的信息char[]要优于String?
7. String vs StringBuilder vs StringBuffer
--------------------------------
4. compareToIgnoreCase(String str)
讲解一:复盘 JavaSE
- 回顾JavaSE入门API篇:字符串(Char & String & StringBuilder & StringBuffer)
--------------------------------
讲解二:基础知识
一、字符串的定义
- 字符串是一种最常用的非数值类型。
- 它是由零个或多个字符组成的有限序列,字符串的逻辑结构与线性表相似,只是数据对象约束为字符集合,字符串的操作中数据元素操作不像线性表那样单个元素操作,而是通常作为一个整体进行操作。
二、字符串的实现
1. 基本介绍
- 串的常用定长顺序存储、堆分配存储和块链存储三种方法实现。
- 串相等:如果两个串的串值相等(相同),称这两个串相等。
换言之,只有当两个串的长度相等,且各个对应位置的字符都相同时才相等。
2. 实现
2.1. 定长顺序存储方式实现
类似于线性表的顺序结构存储,用一组地址连续的存储单元存储串值的字符序列。
在串定长顺序存储结构中,为每个串变量分配一个固定长度的存储区,即定长数组。
代码实现:
public class FixedLengthString {
private final char[] data; // 定长数组存储字符串
public FixedLengthString(int size) {
data = new char[size];
}
// 获取定长字符串的长度
public int length() {
int length = 0;
while (length < data.length && data[length] != '\0') {
length++;
}
return length;
}
// 获取定长字符串的字符
public char charAt(int index) {
if (index >= 0 && index < data.length) {
return data[index];
}
throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + data.length);
}
// 设置定长字符串的字符
public void setCharAt(int index, char ch) {
if (index >= 0 && index < data.length) {
data[index] = ch;
} else {
throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + data.length);
}
}
// 将字符串转换为常规字符串输出
@Override
public String toString() {
return new String(data, 0, length());
}
// 示例用法
public static void main(String[] args) {
FixedLengthString fixedStr = new FixedLengthString(10);
fixedStr.setCharAt(0, 'H');
fixedStr.setCharAt(1, 'e');
fixedStr.setCharAt(2, 'l');
fixedStr.setCharAt(3, 'l');
fixedStr.setCharAt(4, 'o');
System.out.println(fixedStr.toString()); // 输出 "Hello"
System.out.println(fixedStr.length()); // 输出 5
System.out.println(fixedStr.charAt(2)); // 输出 'l'
}
}
这段代码定义了一个 FixedLengthString 类,它使用定长的 char 数组来存储字符串。类中包含了获取字符串
长度、获取指定位置的字符以及设置指定位置的字符的方法。同时,重写了 toString 方法以便于将定长字符串
转换成常规字符串输出。最后,提供了一个 main 方法来演示如何使用这个类。
这里为什么字符串以 \0 结束,这是根据 C 编译器在处理字符数组时会自动为字符串字面量添加一个 \0。
例如,当我们声明 char str[] = "Hello"; 时,编译器会分配6个字节的内存,其中包括 H, e, l, l, o, \0。
这种方式允许字符串可以在数组中占据任何长度,并且 \0 可以出现在任何位置,定义字符串的终止。
这样设计不仅节省了存储空间,也减少了额外的计算开销,因为程序只需要遍历到 \0 即可。
运行结果图如下:
2.2. 堆分配存储方式实现
使用堆存储数据的方式已经学过很多了,线性表在堆中分配空间时分配比较大的一块空间,之后有一个表
示线性表内元素个数的变量控制线性表的操作。
字符串的堆分配存储方式是按照字符串长度分配堆空间,不会额外多分配空间,如果字符串为空,堆中不
分配空间。
在Java中,字符串是用类 String 表示的,而这个类的底层是通过字符数组 char[] 实现的。
Java中的字符串是不可变的,这意味着一旦创建了一个字符串,就不能更改它。
字符串在Java中是用堆分配存储的。
以下是创建和使用字符串的几种方式:
- 直接使用双引号创建字符串:
String str = "Hello, World!";
- 使用 new 关键字和构造函数创建字符串:
String str = new String("Hello, World!");
- 字符数组创建字符串:
char[] charArray = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
String str = new String(charArray);
- 字符串连接:
String str1 = "Hello, ";
String str2 = "World!";
String str3 = str1 + str2; // 使用+运算符进行字符串连接
- 字符串长度:
String str = "Hello, World!";
int length = str.length(); // 获取字符串长度
- 字符串比较:
String str1 = "Hello";
String str2 = "World";
boolean isEqual = str1.equals(str2); // 检查两个字符串是否相等
- 字符串搜索:
String str = "Hello, World!";
boolean contains = str.contains("World"); // 检查字符串是否包含子字符串
- 字符串替换:
String str = "Hello, World!";
String replaced = str.replace("World", "Java"); // 替换字符串中的子串
以上代码展示了创建字符串、使用字符串、字符串操作和字符串属性的基本方法。
在Java中,字符串是不可变的,这意味着一旦创建了字符串,就不能更改它。
当执行字符串连接或其他可能看起来会“更改”字符串的操作时,实际上是创建了一个新的字符串。
这是堆分配存储的一个结果,因为新的字符串需要在堆上创建。
2.3. 块链存储方式实现
待更新(如果有谁能够提供帮助,希望能够将实现的代码私聊留言 - Java 版)
三、字符串匹配算法
1. 基本介绍
字符串匹配在文本处理的广泛领域中是一个非常重要的主题。
字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。
该模式表示为p=p[0..m-1];它的长度等于m。
文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。
一个比较常见的字符串匹配方法工作原理如下。在一个大小通常等于m的窗口帮助下扫描文本。
首先将窗口和文本的左端对齐,然后将窗口的字符与文本中的字符进行比较,这一特定的工作被称为尝
试,在完全匹配或不匹配之后,将窗口移到右侧。继续重复同样的过程,直到窗口的右端超过文本的右
端,一般称为滑动窗口机制。
2. 常见算法
2.1. BF
1> 基本介绍
BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式
串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个
字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。
2> 算法思想
首先S[1]和T[1]比较,若相等,则再比较S[2]和T[2],一直到T[M]为止;若S[1]和T[1]不等,则S向右移动一个字符
的位置,再依次进行比较。
如果存在k,1≤k≤N,且S[k+1…k+M]=T[1…M],则匹配成功;否则失败。
该算法最坏情况下要进行M*(N-M+1)次比较,时间复杂度为O(M*N)。
举例说明:
- S: ababcababa
- T: ababa
BF算法匹配的步骤如下:
i=0, j=0 |
i=1, j=1 |
i=2,j=2 |
i=3, j=3 |
i=4, j=4(失败) |
ababcababa |
ababcababa |
ababcababa |
ababcababa |
ababcababa |
ababa |
ababa |
ababa |
ababa |
ababa |
i=1,j=0(失败) |
ababcababa |
ababa |
i=2,j=0 |
i=3,j=1 |
i=4,j=2(失败) |
ababcababa |
ababcababa |
ababcababa |
ababa |
ababa |
ababa |
i=3,j=0(失败) |
ababcababa |
ababa |
i=4,j=0(失败) |
ababcababa |
ababa |
i=5,j=0 |
i=6,j=1 |
i=7,j=2 |
i=8,j=3 |
i=9,j=4(成功) |
ababcababa |
ababcababa |
ababcababa |
ababcababa |
ababcababa |
ababa |
ababa |
ababa |
ababa |
ababa |
3> 代码实现
public class BFTest {
public static int strMatch(String s, String p){
int i = 0, j = 0;
while(i < s.length() && j < p.length()){
if(s.charAt(i) == p.charAt(j)){
i++;
j++;
}else{
i = i - j + 1;
j = 0;
}
if (j == p.length()){
return i - j;
}
}
return -1;
}
public static void main(String[] args) {
System.out.println( strMatch("ababcababa","ababa"));
}
}
2.2. KMP
1> 基本介绍
KMP算法是三位学者在 Brute-Force算法的基础上同时提出的模式匹配的改进算法。Brute- Force算法在模式串
中有多个字符和主串中的若干个连续字符比较都相等,但最后一个字符比较不相等时,主串的比较位置需要回退。
KMP算法在上述情况下,主串位置不需要回退,从而可以大大提高效率 。
2> 代码实现
public class KMP {
/**
* 求出一个字符数组的next数组
* @param t 字符数组
* @return next数组
*/
public static int[] getNextArray(char[]