Java中檢查字符串是否包含所有唯一字符
瀏覽人數:961最近更新:
1. 概述
在本教程中,我們將學習各種技術來檢查字符串中存在的所有字符(包括非 ASCII 字符)是否唯一。此外,這裡討論的所有方法都不區分大小寫。
2. 暴力破解
這是最明顯的技術之一,但它有點粗糙,而且可能不是最有效的。我們將字符串中的字符相互比較:
public class UniqueCharChecker {
public static boolean bruteForceCheck(String str) {
char[] chars = str.toUpperCase().toCharArray();
for (int i = 0; i < chars.length; i++) {
for (int j = i + 1; j < chars.length; j++) {
if(chars[i] == chars[j]) {
return false;
}
}
}
return true;
}
}
讓我們為上面的方法編寫一些測試用例:
public class UniqueCharCheckerUnitTest {
@Test
public void givenUnique_whenBruteForceCheck_thenReturnTrue() {
String[] sampleStrings = new String[]{"Justfewdi123", "$%&Hibusc", "Hibusc%$#", "მშვნიერ"};
final String MSG = "Duplicate found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertTrue(MSG + " in " + sampleStr, UniqueCharChecker.checkV1(sampleStr)));
}
@Test
public void givenNotUnique_whenBruteForceCheck_thenReturnFalse() {
String[] sampleStrings = new String[]{"Justfewdif123", "$%&Hibushc", "Hibusuc%$#", "Hi%busc%$#", "მშვენიერი"};
final String MSG = "Duplicate not found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertFalse(MSG + " in " + sampleStr, UniqueCharChecker.checkV1(sampleStr)));
}
}
2. 排序
所以這類似於暴力破解技術,但是這裡我們首先對tring
中的字符進行排序,然後將它們與它們的鄰居進行比較,而不是與每個字符進行比較。我們來看看實現:
public static boolean sortAndThenCheck(String str) {
char[] chars = str.toUpperCase().toCharArray();
Arrays.sort(chars);
for (int i = 0; i < chars.length - 1; i++) {
if(chars[i] == chars[i+1]) {
return false;
}
}
return true;
}
我們來測試一下:
@Test
public void givenUnique_whenSortAndThenCheck_thenReturnTrue() {
String[] sampleStrings = new String[]{"Justfewdi123", "$%&Hibusc", "Hibusc%$#", "მშვნიერ"};
final String MSG = "Duplicate found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertTrue(MSG + " in " + sampleStr, UniqueCharChecker.checkV2(sampleStr)));
}
@Test
public void givenNotUnique_whenSortAndThenCheck_thenReturnFalse() {
String[] sampleStrings = new String[]{"Justfewdif123", "$%&Hibushc", "Hibusuc%$#", "Hi%busc%$#", "მშვენიერი"};
final String MSG = "Duplicate not found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertFalse(MSG + " in " + sampleStr, UniqueCharChecker.checkV2(sampleStr)));
}
3. HashSet
在這裡,我們利用java.util.Set to
刪除重複字符:
public static boolean useSetCheck(String str) {
char[] chars = str.toUpperCase().toCharArray();
Set <Character> set = new HashSet <>();
for (char c : chars) {
set.add(c);
}
return set.size() == str.length();
}
現在,讓我們看一下測試用例:
@Test
public void givenUnique_whenUseSetCheck_thenReturnTrue() {
String[] sampleStrings = new String[]{"Justfewdi123", "$%&Hibusc", "Hibusc%$#", "მშვნიერ" };
final String MSG = "Duplicate found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertTrue(MSG + " in " + sampleStr, UniqueCharChecker.checkV3(sampleStr)));
}
@Test
public void givenNotUnique_whenUseSetCheck_thenReturnFalse() {
String[] sampleStrings = new String[]{"Justfewdif123", "$%&Hibushc", "Hibusuc%$#", "Hi%busc%$#", "მშვენიერი"};
final String MSG = "Duplicate not found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertFalse(MSG + " in " + sampleStr, UniqueCharChecker.checkV3(sampleStr)));
}
4.Java 流
此技術與上一節中使用的方法類似。但是,我們使用 Streams API 來創建Set.
我們看一下實現:
public static boolean useStreamCheck(String str) {
boolean isUnique = str.toUpperCase().chars()
.mapToObj(c -> (char) c)
.collect(Collectors.toSet())
.size() == str.length();
return isUnique;
}
讓我們檢查一下單元測試:
@Test
public void givenUnique_whenUseStreamCheck_thenReturnTrue() {
String[] sampleStrings = new String[]{"Justfewdi123", "$%&Hibusc", "Hibusc%$#", "მშვნიერ" };
final String MSG = "Duplicate found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertTrue(MSG + " in " + sampleStr, UniqueCharChecker.checkV1(sampleStr)));
}
@Test
public void givenNotUnique_whenUseStreamCheck_thenReturnFalse() {
String[] sampleStrings = new String[]{"Justfewdif123", "$%&Hibushc", "Hibusuc%$#", "Hi%busc%$#", "მშვენიერი"};
final String MSG = "Duplicate not found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertFalse(MSG + " in " + sampleStr, UniqueCharChecker.checkV4(sampleStr)));
}
5. StringUtils
基本上,在這裡,我們將使用 commons-lang StringUtils
類中的containsIgnoreCase()
方法:
public static boolean useStringUtilscheck(String str) {
for (int i = 0; i < str.length(); i++) {
String curChar = String.valueOf(str.charAt(i));
String remainingStr = str.substring(i+1);
if(StringUtils.containsIgnoreCase(remainingStr, curChar)) {
return false;
}
}
return true;
}
我們來測試一下這個方法:
@Test
public void givenUnique_whenUseStringUtilscheck_thenReturnTrue() {
String[] sampleStrings = new String[]{"Justfewdi123", "$%&Hibusc", "Hibusc%$#", "მშვნიერ"};
final String MSG = "Duplicate found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertTrue(MSG + " in " + sampleStr, UniqueCharChecker.checkV5(sampleStr)));
}
@Test
public void givenNotUnique_whenUseStringUtilscheck_thenReturnFalse() {
String[] sampleStrings = new String[]{"Justfewdif123", "$%&Hibushc", "Hibusuc%$#", "Hi%busc%$#", "მშვენიერი"};
final String MSG = "Duplicate not found";
Arrays.stream(sampleStrings)
.forEach(sampleStr -> assertFalse(MSG + " in " + sampleStr, UniqueCharChecker.checkV5(sampleStr)));
}
六,結論
在本教程中,我們看到了五種不同的方法來檢查字符串是否具有唯一字符。我們還得出結論,沒有現成的庫可用於解決此問題。
此處使用的代碼片段以及相關的 JUnit 測試用例可在 GitHub 上獲取。
本作品係原創或者翻譯,採用《署名-非商業性使用-禁止演繹4.0國際》許可協議