1. 介紹:為什麼字串搜尋在 Java 中很重要
字串操作是 Java 程式開發中最常使用的操作之一。
無論是檢查使用者輸入、解析檔案內容,或是搜尋特定關鍵字,您常常需要判斷某個字是否出現在給定的字串中。
為了滿足這些需求,Java 提供了一個方便的方法 contains()。
使用此方法,您可以輕鬆判斷一個字串 是否部份包含 另一個字串。
例如,若要檢查錯誤訊息是否包含特定關鍵字,contains() 只需要一行程式碼即可完成。
特別是在處理大量文字的情境——如 Web 應用、API 處理或日誌分析——contains() 方法能大幅提升程式碼的可讀性與可維護性。
然而,也必須注意大小寫敏感性以及 null 的可能性等重要考量。
本文將詳細說明 Java 的 contains() 方法——從基本用法與常見錯誤,到與其他方法的差異與實務應用。
我們的目標是提供對初學者以及在實務專案中使用 Java 的開發者皆有用的資訊。
2. contains() 方法的基本語法與特性
Java 的 contains() 方法用來判斷字串 是否部份包含 另一個字串。
語法非常簡單,但在日常程式開發中卻相當實用且常被使用。
基本語法
boolean result = targetString.contains(searchString);
此方法屬於 String 類別,接受一個 CharSequence(通常是 String)作為參數。
回傳值為 boolean:若目標字串包含給定的子字串則回傳 true,否則回傳 false。
範例程式碼
String message = "Java programming is fun!";
boolean hasKeyword = message.contains("programming");
System.out.println(hasKeyword); // Output: true
在上述範例中,子字串 "programming" 出現在目標字串中,因此 contains() 會回傳 true。
方法的特性
- 僅檢查部份匹配:若需要完全相等,請改用
equals()。 - 大小寫敏感:例如,
"Java"與"java"會被視為不同(稍後會說明細節)。 - 不支援正規表達式:因為它僅檢查字串是否存在,若需模式匹配請使用
matches()或Pattern類別。
傳入 null 時的行為
將 null 傳給 contains() 會拋出 NullPointerException。
例如,以下程式碼會產生例外:
String text = null;
System.out.println(text.contains("test")); // Exception occurs
同樣地,若目標字串本身為 null,也會拋出相同的例外。
因此,強烈建議在呼叫 contains() 之前 先做 null 檢查。
3. 實務使用範例與重要注意事項
Java 的 contains() 方法直觀且方便,但不當使用可能導致意外的錯誤或低效的程式碼。
本節說明 contains() 的基本用法,並提醒您在使用時需要留意的關鍵點。
3-1. 基本使用範例
以下程式碼示範了檢查目標字串是否包含特定關鍵字的簡單範例:
String sentence = "今日はJavaの勉強をしています。";
if (sentence.contains("Java")) {
System.out.println("Javaが含まれています。");
} else {
System.out.println("Javaは含まれていません。");
}
如範例所示,contains() 常與 if 陳述式結合,用以執行條件分支。
3-2. 大小寫敏感性
contains() 方法是 大小寫敏感 的。
例如,以下程式碼會回傳 false:
String text = "Welcome to Java";
System.out.println(text.contains("java")); // false
在這種情況下,通常會在比較前 將字串轉成小寫(或大寫):
String text = "Welcome to Java";
System.out.println(text.toLowerCase().contains("java")); // true
此方法有助於消除輸入大小寫的差異(例如,使用者輸入)。
3-3. null 與空字串的處理
使用 contains() 時最重要的考量之一是 null 的處理。
如果目標字串或參數為 null,將拋出 NullPointerException。
String text = null;
System.out.println(text.contains("test")); // Runtime error
為避免此問題,請始終先做 null 檢查:
if (text != null && text.contains("test")) {
// Safe to process
}
另請注意:
傳入空字串 ("") 總是會回傳 true。
String sample = "test";
System.out.println(sample.contains("")); // true
然而,這種行為在實務上很少有用,且若不小心傳入空字串,可能會意外產生 bug。
3-4. 不支援多關鍵字搜尋
contains() 一次只能檢查一個關鍵字。
若要檢查多個關鍵字,必須多次呼叫 contains(),或改用 Stream API。
String target = "エラーコード123:アクセス拒否";
if (target.contains("エラー") || target.contains("拒否")) {
System.out.println("問題のあるメッセージです。");
}
或是使用動態關鍵字集合:
List<String> keywords = Arrays.asList("エラー", "障害", "失敗");
boolean found = keywords.stream().anyMatch(target::contains);
4. 常與 contains() 比較的其他方法
Java 提供了多種字串比較或檢查子字串是否存在的方法。
其中 contains() 用於「部分匹配」,但其他方法也有類似的用途。
本節說明這些方法的特性與差異,協助您正確選擇使用。
4-1. 與 equals() 的差異:完全匹配 vs. 部分匹配
equals() 判斷 兩個字串是否完全相同。
相較之下,contains() 只檢查部分匹配。
String a = "Java";
String b = "Java";
System.out.println(a.equals(b)); // true: Exact match
System.out.println(a.contains("av")); // true: Partial match
主要差異:
| Comparison | equals() | contains() |
|---|---|---|
| Match Type | Exact match | Partial match |
| Case Sensitivity | Sensitive | Sensitive |
| Argument Type | Object | CharSequence |
使用指引:
– 必須完全相同時(例如 ID 驗證),使用 equals()。
– 只要部分匹配即可(例如關鍵字搜尋),使用 contains()。
4-2. 與 indexOf() 的差異:是否需要取得位置
indexOf() 也可用來檢查子字串是否存在於字串中。
不同之處在於,indexOf() 會回傳子字串的 起始索引(若找到),未找到則回傳 -1。
String text = "Hello, Java World!";
System.out.println(text.indexOf("Java")); // 7
System.out.println(text.indexOf("Python")); // -1
您也可以使用 indexOf() 來模擬 contains() 的行為:
if (text.indexOf("Java") >= 0) {
System.out.println("It is contained.");
}
使用指引:
如果不需要索引,contains() 更具可讀性且較為適合。
4-3. 與 matches() 的差異:支援正規表達式
matches() 檢查字串是否 完整符合給定的正規表達式。
相較之下,contains() 只檢查字面子字串,並不支援正規表達式。
String text = "abc123";
System.out.println(text.matches(".*123")); // true
System.out.println(text.contains(".*123")); // false (not regex)
若需要正規表達式的部分匹配,請使用 Pattern 類別:
4-4. 功能比較摘要
| Method | Purpose | Return Type | Regex Support | Use Case |
|---|---|---|---|---|
contains() | Partial match | boolean | No | Keyword search |
equals() | Exact match | boolean | No | ID/password checks |
indexOf() | Get match position | int | No | Index-based processing |
matches() | Regex match | boolean | Yes | Find pattern-based strings |
5. 常見使用情境與範例程式碼
Java 的 contains() 方法簡單卻在實務開發中被廣泛使用。
典型的使用情境包括使用者輸入驗證、日誌分析與過濾操作。
本節提供實作範例與相應程式碼。
5-1. 使用者輸入驗證(偵測禁用詞)
在表單或聊天應用程式中,您可能需要偵測是否包含某些禁用詞彙。
String input = "このアプリは最悪だ";
String banned = "最悪";
if (input.contains(banned)) {
System.out.println("不適切な言葉が含まれています。");
}
處理多個 NG(禁用)詞彙:
List<String> bannedWords = Arrays.asList("最悪", "バカ", "死ね");
for (String word : bannedWords) {
if (input.contains(word)) {
System.out.println("不適切な言葉が含まれています: " + word);
break;
}
}
5-2. 日誌檔案分析(偵測特定訊息)
在分析系統或應用程式日誌時,您可能只想提取包含特定關鍵字(如 ERROR 或 WARN)的行。
List<String> logs = Arrays.asList(
"[INFO] サーバーが起動しました",
"[ERROR] データベース接続失敗",
"[WARN] メモリ使用率が高い"
);
for (String log : logs) {
if (log.contains("ERROR")) {
System.out.println("エラー発生ログ: " + log);
}
}

5-3. 篩選清單中的字串(使用 Stream API)
處理大型資料集時,使用 Stream API 只提取包含特定子字串的元素:
List<String> users = Arrays.asList("tanaka@example.com", "sato@gmail.com", "yamada@yahoo.co.jp");
List<String> gmailUsers = users.stream()
.filter(email -> email.contains("@gmail.com"))
.collect(Collectors.toList());
System.out.println(gmailUsers); // [sato@gmail.com]
5-4. 解析 HTTP 請求標頭或 URL
在 Web 開發中,路由或裝置特定的處理可能需要檢查 User-Agent 或 URL 中的子字串。
String userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)";
if (userAgent.contains("iPhone")) {
System.out.println("スマートフォンからのアクセスです。");
}
5-5. 檢查檔案路徑或副檔名
透過檔案路徑判斷檔案類型:
String filePath = "/usr/local/data/sample.csv";
if (filePath.contains(".csv")) {
System.out.println("CSVファイルです。");
}
注意:
對於副檔名檢查,使用 endsWith(".csv") 通常更精確。
實務考量
- 在需要精確時,請先正規化(例如
toLowerCase()、trim())。 - 針對大規模資料,考慮使用 Stream API 或正規表達式。
- 請記得
contains()為部分匹配——結合其他條件以確保邏輯更安全。
6. 效能考量
雖然 contains() 方法具備極佳的可讀性與簡潔性,但在處理大型資料集或執行重複操作時,必須考量其 效能影響。本節說明 contains() 的處理成本以及提升效能的替代方法。
6-1. contains() 的內部行為與時間複雜度
contains() 方法會 從字串開頭依序 搜尋目標字串,以找出子字串。
在內部,它依賴 indexOf() 方法,其最壞情況的時間複雜度為:
O(n × m)
– n = 目標字串的長度
– m = 搜尋字串的長度
大量處理的範例:
for (String line : hugeTextList) {
if (line.contains("error")) {
// processing
}
}
在大型迴圈中重複執行時,這可能會顯著影響效能。
6-2. 提升頻繁搜尋效能的技巧
在大型資料集中頻繁使用 contains() 時,以下技巧可提升處理速度:
• 事先將所有字串轉為小寫
與其在每次比較時呼叫 toLowerCase(),不如事先正規化字串:
List<String> normalizedList = originalList.stream()
.map(String::toLowerCase)
.collect(Collectors.toList());
• 使用帶有 parallel() 的 Stream API 進行平行處理
利用 CPU 核心加速搜尋:
List<String> result = hugeTextList.parallelStream()
.filter(line -> line.contains("keyword"))
.collect(Collectors.toList());
• 使用正規表達式處理複雜的搜尋模式
如果條件較為複雜且能以單一正規表達式表示,Pattern 可能會有更好的效能:
Pattern pattern = Pattern.compile("error|fail|fatal");
for (String log : logs) {
if (pattern.matcher(log).find()) {
// matched
}
}
6-3. 記憶體效率與可重用性考量
頻繁執行字串轉換的操作——例如 toLowerCase() 或 substring()——可能會產生 大量不必要的字串物件,進而影響記憶體使用。這在長時間執行的應用程式或伺服器端處理時尤為重要。
重點:
- 避免建立不必要的字串實例。
- 對於大型資料集,考慮使用緩衝或分塊處理。
- 快取重複的
contains()結果在某些情況下可提升效能。
7. 與其他程式語言的比較
Java 的 contains() 方法提供簡單、可靠的子字串匹配,但其他語言也有類似功能,且各自具備不同特性。本節比較 Python、JavaScript 與 C# 的子字串檢查,以突顯差異與相似之處。
7-1. Python:使用 in 運算子進行簡易部分匹配
在 Python 中,可使用 in 運算子檢查子字串是否存在:
text = "Hello, Python!"
if "Python" in text:
print("含まれています")
此語法極為易讀——幾乎像自然語言,且學習成本極低。
差異與說明:
in是語言層級的運算子,而非方法。- Python 也對字串比較區分大小寫。
None會拋出例外,必須先做 null 檢查。
7-2. JavaScript:使用 includes() 進行部分匹配
在 JavaScript(ES6 以上)中,可使用 includes() 方法:
const text = "JavaScript is fun";
console.log(text.includes("fun")); // true
此方法與 Java 的 contains() 十分相似,心智模型易於遷移。
差異與說明:
- 傳入
undefined不會拋出例外,只會回傳false。 includes()也可用於陣列,提升了多樣性。
7-3. C#:Contains() 與 Java 類似
C# 同樣提供 Contains() 方法,行為與 Java 相近:
string text = "Welcome to C#";
bool result = text.Contains("C#");
差異與說明:
- C# 的
Contains()預設區分大小寫,但可透過StringComparison.OrdinalIgnoreCase來忽略大小寫。 - 傳入 null 會拋出
ArgumentNullException。
7-4. 各語言比較表
| Language | Example Syntax | Case Sensitivity | Notes |
|---|---|---|---|
| Java | "abc".contains("a") | Sensitive | Throws exception on null |
| Python | "a" in "abc" | Sensitive | Most intuitive syntax |
| JavaScript | "abc".includes("a") | Sensitive | Also works for arrays |
| C# | "abc".Contains("a") | Sensitive (configurable) | Comparison mode can be chosen |
小結:依需求選擇適合的語法
雖然子字串檢查是跨語言的常見需求,但每種語言都提供各自的方式或語法。Java 的 contains() 具備穩定性與可讀性,特別適合企業系統與可維護的應用程式。Python 與 JavaScript 則提供更簡潔的語法,適合輕量腳本或快速原型開發。了解共通概念與各語言的特殊功能後,您即可在不同語言間撰寫更安全且高效的程式碼。
8. 常見問題集 (FAQ)
以下列出關於 Java contains() 方法的常見問題,協助您釐清疑點並避免常見陷阱。
Q1. contains() 是否區分大小寫?
是的,contains() 會區分大小寫。
例如,"Java".contains("java") 會回傳 false。
解決方式:
String input = "Welcome to Java";
boolean result = input.toLowerCase().contains("java");
Q2. 如何使用正規表達式進行部分匹配?
contains() 不支援正規表達式。
請改用 matches() 或 Pattern 類別。
範例(檢查數字模式):
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String text = "注文番号: A123456";
Pattern pattern = Pattern.compile("A\d+");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("パターンに一致しました。");
}
Q3. 如果對 null 呼叫 contains() 會發生什麼事?
會拋出 NullPointerException。
String target = null;
System.out.println(target.contains("test")); // Error
解決方案:
if (target != null && target.contains("test")) {
System.out.println("含まれています。");
}
Q4. 如果傳入空字串 (“”) 給 contains() 會發生什麼事?
它總是回傳 true。
String text = "Java";
System.out.println(text.contains("")); // true
雖然此行為屬於官方規範的一部份,但實際上很少有用處,若未預期空字串,可能會導致意外的錯誤。
Q5. contains() 能一次搜尋多個關鍵字嗎?
不能。每次呼叫只能檢查一個關鍵字。
String text = "本日はシステムエラーが発生しました";
if (text.contains("エラー") || text.contains("障害") || text.contains("失敗")) {
System.out.println("問題が検出されました。");
}
動態方式:
List<String> keywords = Arrays.asList("エラー", "障害", "失敗");
boolean found = keywords.stream().anyMatch(text::contains);
Q6. 何時該使用 contains() 而非 indexOf()?
contains() 回傳布林值,而 indexOf() 回傳數值索引。
- 當你只想知道子字串是否存在時,使用
contains()。 - 當你同時需要取得位置時,使用
indexOf()。String text = "Error: Disk full"; if (text.contains("Error")) { int pos = text.indexOf("Error"); System.out.println("Position: " + pos); }
9. 結論
Java 的 contains() 方法是一個強大且便利的工具,用於判斷特定子字串是否 包含在字串中。
它廣泛應用於使用者輸入驗證、日誌分析與資料過濾等各種情境。
在本文中,我們討論了:
- 基本語法與回傳值
- 大小寫敏感性與處理方式
- 處理 null 與空字串
- 與其他字串比較方法的差異
- 實務應用案例:驗證、日誌搜尋、Stream 處理
- 效能考量與最佳化技巧
- 與 Python、JavaScript、C# 的比較
- 常見問答與除錯技巧
雖然 contains() 直觀且多功能,但在涉及 大型資料集、頻繁呼叫 或 複雜搜尋條件 的情況下,仍需謹慎評估其使用。
透過結合正規化、平行處理、正規表達式與快取策略,可同時維持效能與可讀性。
由於 contains() 是 Java 字串操作的基礎,我們期望本文能協助你在開發專案中更安全、有效地使用它。

