深圳幻海软件技术有限公司 欢迎您!

【LeetCode算法成长之路】Java字符串相关类总结与经典题目分析

2023-04-19

前言本文小新为大家带来Java字符串相关类总结与经典题目分析相关知识,具体内容包括不可变字符序列String介绍(包括:String的特性,String的构造器,String与其他结构间的转换,String的基本常用方法,String的查找方法,String的字符串截取方法,String的和字符/字

前言

本文小新为大家带来 Java字符串相关类总结与经典题目分析 相关知识,具体内容包括不可变字符序列String介绍(包括:String 的特性String 的构造器String 与其他结构间的转换String 的基本常用方法String 的查找方法String 的字符串截取方法String 的和字符/字符数组相关方法String 的开头与结尾判断方法String 的替换方法),可变字符序列StringBuffer与StringBuilder(包括:StringBuffer 与 StringBuilder 的理解StringBuilder、StringBuffer 的 API),字符串操作经典算法题目(包括:去除字符串两端的空格将字符串进行反转一个字符串在另一个字符串中出现的次数两个字符串中的最大相同子串对字符串中字符进行自然顺序排序)等进行详尽介绍~

不积跬步,无以至千里;不积小流,无以成江海。每天进步一点点,在成为强者的路上,小新与大家共同成长!

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)


目录

Java字符串相关类总结与经典题目分析

  • 前言
  • 目录
  • 一、不可变字符序列String
    • 1️⃣String 的特性
    • 2️⃣String 的构造器
    • 3️⃣String 与其他结构间的转换
    • 4️⃣String 的基本常用方法
    • 5️⃣String 的查找方法
    • 6️⃣String 的字符串截取方法
    • 7️⃣String 的和字符/字符数组相关方法
    • 8️⃣String 的开头与结尾判断方法
    • 9️⃣String 的替换方法
  • 二、可变字符序列StringBuffer与StringBuilder
    • 1️⃣StringBuffer 与 StringBuilder 的理解
    • 2️⃣StringBuilder、StringBuffer 的 API
  • 三、字符串操作经典算法题目
    • 1️⃣题目1:去除字符串两端的空格
    • 2️⃣题目2:将字符串进行反转
    • 3️⃣题目3:一个字符串在另一个字符串中出现的次数
    • 4️⃣题目4:两个字符串中的最大相同子串
    • 5️⃣题目5:对字符串中字符进行自然顺序排序
  • 后记

在LeetCode算法题目中有许多 关于字符串的题目,对于这些题目,如果我们需要熟练掌握Java中的字符串类,包括其中常用的方法,对于这类题目就可以游刃有余。

下面会先为大家对不可变字符序列String,及可变字符序列StringBuffer与StringBuilder进行介绍,并为大家总结有关的常用方法,最后为大家展示几道与字符串有关的经典算法题目。

一、不可变字符序列String

1️⃣String 的特性

  • java.lang.String 类代表字符串。Java 程序中所有的字符串文字(例如 “hello” )都可以看作是实现此类的实例。
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
  • 字符串 String 类型本身是 final 声明的,意味着我们不能继承String。
  • String 对象的字符内容是存储在一个字符数组 value[]中的。“abc” 等效于 char[] data={‘h’,‘e’,‘l’,‘l’,‘o’}。

  • Java 语言提供对字符串串联符号(“+”)以及将其他对象转换为字符串的特殊支持(toString()方法)。

2️⃣String 的构造器

  • public String() :初始化新创建的 String 对象,以使其表示空字符序列。
  • String(String original): 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
  • public String(char[] value) :通过当前参数中的字符数组来构造新的String。
  • public String(char[] value,int offset, int count) :通过字符数组的 一部分来构造新的String。
  • public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的 String。
  • public String(byte[] bytes,String charsetName) :通过使用指定的字符集解码当前参数中的字节数组来构造新的 String。

3️⃣String 与其他结构间的转换

🍀字符串 --> 基本数据类型、包装类

  • Integer 包装类的 public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
  • 类似地,使用 java.lang 包中的 Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。

🍀基本数据类型、包装类 --> 字符串

  • 调用 String 类的 public String valueOf(int n)可将 int 型转换为字符串。
  • 相应的 valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换。

🍀字符数组 --> 字符串

  • String 类的构造器:String(char[]) 和 String(char[],int offset,int length)
    分别用字符数组中的全部字符和部分字符创建字符串对象。

🍀字符串 --> 字符数组

  • public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
  • public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。

🍀字符串 --> 字节数组(编码)

  • public byte[] getBytes() :使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte 数组中。
  • public byte[] getBytes(String charsetName) :使用指定的字符集将此String编码到byte 序列,并将结果存储到新的 byte 数组。

🍀字节数组 --> 字符串(解码)

  • String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的String。
  • String(byte[],int offset,int length) :用指定的字节数组的一部分,即从数组起始位置 offset开始取 length 个字节构造一个字符串对象。
  • String(byte[], String charsetName ) 或 new String(byte[], int, int,String charsetName ):解码,按照指定的编码方式进行解码。

4️⃣String 的基本常用方法

String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。

  • (1)boolean isEmpty():字符串是否为空
  • (2)int length():返回字符串的长度
  • (3)String concat(xx):拼接
  • (4)boolean equals(Object obj):比较字符串是否相等,区分大小写
  • (5)boolean equalsIgnoreCase(Object obj):比较字符串是否相等,不区分大小写
  • (6)int compareTo(String other):比较字符串大小,区分大小写,按照 Unicode 编码值比较大小
  • (7)int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
  • (8)String toLowerCase():将字符串中大写字母转为小写
  • (9)String toUpperCase():将字符串中小写字母转为大写
  • (10)String trim():去掉字符串前后空白符
  • (11)public String intern():结果在常量池中共享

5️⃣String 的查找方法

  • (1)boolean contains(xx):是否包含 xx
  • (2)int indexOf(xx):从前往后找当前字符串中 xx,即如果有返回第一次出现的下标,要是没有返回-1
  • (3)int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
  • (4)int lastIndexOf(xx):从后往前找当前字符串中 xx,即如果有返回最后一次出现的下标,要是没有返回-1
  • (5)int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。

6️⃣String 的字符串截取方法

  • (1)String substring(int beginIndex) :返回一个新的字符串,它是此字符串的从 beginIndex开始截取到最后的一个子字符串。
  • (2)String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到 endIndex(不包含)的一个子字符串。

7️⃣String 的和字符/字符数组相关方法

  • (1)char charAt(index):返回[index]位置的字符。
  • (2)char[] toCharArray(): 将此字符串转换为一个新的字符数组返回 。
  • (3)static String valueOf(char[] data) :返回指定数组中表示该字符序列的 String 。
  • (4)static String valueOf(char[] data, int offset, int count) :返回指定数组中表示该字符序列的 String 。
  • (5)static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String 。
  • (6)static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String。

8️⃣String 的开头与结尾判断方法

  • (1)boolean startsWith(xx):测试此字符串是否以指定的前缀开始 。
  • (2)boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
  • (3)boolean endsWith(xx):测试此字符串是否以指定的后缀结束。

9️⃣String 的替换方法

  • (1)String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar替换此字符串中出现的所有 oldChar 得到的。 不支持正则。
  • (2)String replace(CharSequence target, CharSequence replacement): 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
  • (3)String replaceAll(String regex, String replacement):使用给定的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
  • (4)String replaceFirst(String regex, String replacement):使用给定的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

二、可变字符序列StringBuffer与StringBuilder

因为 String 对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低,空间消耗也比较高。因此,JDK 又在java.lang包提供了可变字符序列 StringBuffer 和 StringBuilder 类型。

1️⃣StringBuffer 与 StringBuilder 的理解

  • java.lang.StringBuffer 代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。比如:
//情况 1:
String s = new String("我喜欢学习");
//情况 2:
StringBuffer buffer = new StringBuffer("我喜欢学习");
buffer.append("数学");
  • 1
  • 2
  • 3
  • 4
  • 5

  • StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且提供相关功能 的方法也一样。
  • 区分 String、StringBuffer、StringBuilder:
  • String:不可变的字符序列; 底层使用 char[]数组存储(JDK8.0 中)
  • StringBuffer:可变的字符序列;线程安全(方法有 synchronized 修饰),效率低;底层使用 char[]数组存储 (JDK8.0 中)
  • StringBuilder:可变的字符序列; jdk1.5 引入,线程不安全的,效率高;底 层使用 char[]数组存储(JDK8.0中)

2️⃣StringBuilder、StringBuffer 的 API

StringBuilder、StringBuffer 的 API 是完全一致的,并且很多方法与 String 相同。

🍀常用 API

  • (1)StringBuffer append(xx):提供了很多的 append()方法,用于进行字符串追加的方式拼接
  • (2)StringBuffer delete(int start, int end):删除[start,end)之间字符
  • (3)StringBuffer deleteCharAt(int index):删除[index]位置字符
  • (4)StringBuffer replace(int start, int end, String str):替换[start,end)范围的字符序列为 str
  • (5)void setCharAt(int index, char c):替换[index]位置字符
  • (6)char charAt(int index):查找指定 index 位置上的字符
  • (7)StringBuffer insert(int index, xx):在[index]位置插入 xx
  • (8)int length():返回存储的字符数据的长度
  • (9)StringBuffer reverse():反转

🍀与 String相同的方法

  • (1)int indexOf(String str):在当前字符序列中查询 str 的第一次出现下标
  • (2)int indexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询str 的第一次出现下标
  • (3)int lastIndexOf(String str):在当前字符序列中查询 str 的最后一次出现下标
  • (4)int lastIndexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询 str 的最后一次出现下标
  • (5)String substring(int start):截取当前字符序列[start,最后]
  • (6)String substring(int start, int end):截取当前字符序列[start,end)
  • (7)String toString():返回此序列中数据的字符串表示形式
  • (8)void setLength(int newLength) :设置当前字符序列长度为newLength

三、字符串操作经典算法题目

1️⃣题目1:去除字符串两端的空格

模拟一个 trim 方法,去除字符串两端的空格。

public String myTrim(String str) {
  if (str != null) {
    int start = 0;// 用于记录从前往后首次索引位置不是空格的位置的索引
    int end = str.length() - 1;// 用于记录从后往前首次索引位置不是空格的位置的索引
    while (start < end && str.charAt(start) == ' ') {
      start++;
    }
    while (start < end && str.charAt(end) == ' ') {
      end--;
    }
    if (str.charAt(start) == ' ') {
      return "";
    }
    return str.substring(start, end + 1);
  }
  return null;
}

@Test
public void testMyTrim() {
  String str = " a ";
  // str = " ";
  String newStr = myTrim(str);
  System.out.println("---" + newStr + "---");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

2️⃣题目2:将字符串进行反转

将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”。

// 方式一:
public String reverse1(String str, int start, int end) {// start:2,end:5
  if (str != null) {
  // 1.
  char[] charArray = str.toCharArray();
  // 2.
  for (int i = start, j = end; i < j; i++, j--) {
    char temp = charArray[i];
    charArray[i] = charArray[j];
    charArray[j] = temp;
  }
  // 3.
  return new String(charArray);
  }
  return null;
}

// 方式二:
public String reverse2(String str, int start, int end) {
  // 1.
  String newStr = str.substring(0, start);// ab
  // 2.
  for (int i = end; i >= start; i--) {
    newStr += str.charAt(i);
  } // abfedc
  // 3.
  newStr += str.substring(end + 1);
  return newStr;
}

// 方式三:推荐 (相较于方式二做的改进)
public String reverse3(String str, int start, int end) {// ArrayLi
  st list = new ArrayList(80);
  // 1.
  StringBuffer s = new StringBuffer(str.length());
  // 2.
  s.append(str.substring(0, start));// ab
  // 3.
  for (int i = end; i >= start; i--) {
    s.append(str.charAt(i));
  }
  // 4.
  s.append(str.substring(end + 1));
  // 5.
  return s.toString();
}

@Test
public void testReverse() {
  String str = "abcdefg";
  String str1 = reverse3(str, 2, 5);
  System.out.println(str1);// abfedcg
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

3️⃣题目3:一个字符串在另一个字符串中出现的次数

获取一个字符串在另一个字符串中出现的次数。 比如:获取“ ab”在“abkkcadkabkebfkabkskab” 中出现的次数。

// 判断 str2 在 str1 中出现的次数
public int getCount(String mainStr, String subStr) {
  if (mainStr.length() >= subStr.length()) {
    int count = 0;
    int index = 0;
    // while((index = mainStr.indexOf(subStr)) != -1){
    //   count++;
    //   mainStr = mainStr.substring(index + subStr.length());
    // }
    // 改进:
    while ((index = mainStr.indexOf(subStr, index)) != -1) {
      index += subStr.length();
      count++;
    }
    return count;
  } else {
    return 0;
  }
}

@Test
public void testGetCount() {
  String str1 = "cdabkkcadkabkebfkabkskab";
  String str2 = "ab";
  int count = getCount(str1, str2);
  System.out.println(count);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

4️⃣题目4:两个字符串中的最大相同子串

获取两个字符串中最大相同子串。比如: str1 = "abcwerthelloyuiodef“; str2 = “cvhellobnm” 提示:将短的那个串进行长度依次递减的子串与较长的串比较。

// 如果只存在一个最大长度的相同子串
public String getMaxSameSubString(String str1, String str2) {
  if (str1 != null && str2 != null) {
    String maxStr = (str1.length() > str2.length()) ? str1 : str2;
    String minStr = (str1.length() > str2.length()) ? str2 : str1;
    int len = minStr.length();
    for (int i = 0; i < len; i++) {// 0 1 2 3 4 此层循环决定要去几个字符
      for (int x = 0, y = len - i; y <= len; x++, y++) {
        if (maxStr.contains(minStr.substring(x, y))) {
          return minStr.substring(x, y);
        }
      }
    }
  }
  return null;
}

// 如果存在多个长度相同的最大相同子串
// 此时先返回 String[],后面可以用集合中的 ArrayList 替换,较方便
public String[] getMaxSameSubString1(String str1, String str2) {
  if (str1 != null && str2 != null) {
    StringBuffer sBuffer = new StringBuffer();
    String maxString = (str1.length() > str2.length()) ? str1 : str2;
    String minString = (str1.length() > str2.length()) ? str2 : str1;
    int len = minString.length();
    for (int i = 0; i < len; i++) {
      for (int x = 0, y = len - i; y <= len; x++, y++) {
        String subString = minString.substring(x, y);
        if (maxString.contains(subString)) {
          sBuffer.append(subString + ",");
        }
      }
      System.out.println(sBuffer);
      if (sBuffer.length() != 0) {
        break;
      }
    }
    String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,");
    return split;
  }
  return null;
}

// 如果存在多个长度相同的最大相同子串:使用 ArrayList
// public List<String> getMaxSameSubString1(String str1, String str2) {
//   if (str1 != null && str2 != null) {
//     List<String> list = new ArrayList<String>();
//     String maxString = (str1.length() > str2.length()) ? str1 : str2;
//     String minString = (str1.length() > str2.length()) ? str2 : str1;
//
//     int len = minString.length();
//     for (int i = 0; i < len; i++) {
//       for (int x = 0, y = len - i; y <= len; x++, y++) {
//         String subString = minString.substring(x, y);
//         if (maxString.contains(subString)) {
//           list.add(subString);
//         }
//       }
//       if (list.size() != 0) {
//         break;
//       }
//     }
//     return list;
//   }
//   return null;
// }

@Test
public void testGetMaxSameSubString() {
  String str1 = "abcwerthelloyuiodef";
  String str2 = "cvhellobnmiodef";
  String[] strs = getMaxSameSubString1(str1, str2);
  System.out.println(Arrays.toString(strs));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

5️⃣题目5:对字符串中字符进行自然顺序排序

对字符串中字符进行自然顺序排序。

提示:

  • 1)字符串变成字符数组;
  • 2)对数组排序,选择,冒泡,Arrays.sort();
  • 3)将排序后的数组变成字符串。
@Test
public void testSort() {
  String str = "abcwerthelloyuiodef";
  char[] arr = str.toCharArray();
  Arrays.sort(arr);
  String newStr = new String(arr);
  System.out.println(newStr);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

后记

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览44428 人正在系统学习中
欢迎与小新交流哦~
微信名片