1. 在集合中搜尋元素
使用標準方法進行搜尋
當我們有一個清單,例如名字:
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
Java 提供了幾個方便的方法來搜尋:
- contains(Object o) — 檢查集合中是否存在該元素。
- indexOf(Object o) — 回傳元素第一次出現的索引(若未找到則為 -1)。
- lastIndexOf(Object o) — 回傳元素最後一次出現的索引(或 -1)。
範例:
System.out.println(names.contains("Anna")); // true
System.out.println(names.indexOf("Anna")); // 0
System.out.println(names.lastIndexOf("Anna")); // 3
System.out.println(names.contains("Sergey")); // false
事實:對於 Set 類型的集合,沒有 indexOf 與 lastIndexOf —— 在 Set 中根本沒有索引,只有唯一值。
依條件搜尋
有時需要找的不是具體值,而是符合某個條件的元素。比如,找到第一個長度大於 6 的名字。一般的 for 迴圈就很適合:一旦找到符合條件的元素——使用 break。
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
String found = null;
for (String name : names) {
if (name.length() > 6) {
found = name;
break; // 找到第一個符合條件的項目,就可以跳出迴圈
}
}
System.out.println(found); // Viktoriya
尋找最大值與最小值
對於可比較的元素(例如數字),可以使用 Collections 類別快速找到最大值與最小值。
List<Integer> numbers = List.of(10, 5, 20, 7, 20, 3);
int max = Collections.max(numbers); // 20
int min = Collections.min(numbers); // 3
System.out.println("最大值: " + max);
System.out.println("最小值: " + min);
重要:元素必須是可比較的(實作 Comparable),否則需要傳入比較器。
2. 集合的排序
預設的清單排序
只有可變的清單(例如 ArrayList、LinkedList)才能排序。Set 與 Map 這類集合無法直接排序。
預設按「自然順序」排序:對數字而言是遞增,對字串而言是字母順序。
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
也可以透過清單的 sort 方法做到相同效果:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null 表示:使用自然順序
System.out.println(numbers); // [1, 3, 5, 7]
使用 Comparator 排序
如果需要自訂規則——例如,依字串長度排序:
List<String> words = new ArrayList<>(List.of("kot", "slon", "mukha", "nosorog"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [kot, slon, mukha, nosorog]
反向排序:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [nosorog, mukha, slon, kot]
舊寫法,透過 Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. 不同集合排序的特性
排序只會修改清單
排序方法(sort、Collections.sort)只適用於支援元素順序的集合(例如 List)。對 Set 與 Map 並未提供這些方法。
嘗試對 Set 排序:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // 編譯錯誤:sort 需要的是 List!
如果需要從 Set 取得一個已排序的清單:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
Map 的排序:依鍵或依值
不能直接對 Map 排序,但可以:
- 取得「鍵-值」配對的清單
- 依所需方式進行排序
- 必要時再組裝成新的 Map
範例:依值排序
Map<String, Integer> scores = Map.of(
"Anna", 15,
"Boris", 20,
"Vika", 12
);
List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Vika: 12
// Anna: 15
// Boris: 20
依欄位對物件排序
假設我們有一個使用者類別:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
以及一個使用者清單:
List<User> users = new ArrayList<>(List.of(
new User("Anna", 22),
new User("Boris", 18),
new User("Vika", 25)
));
依年齡排序:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Boris (18), Anna (22), Vika (25)]
反向排序:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Vika (25), Anna (22), Boris (18)]
4. 在搜尋與排序集合時的常見錯誤
錯誤 №1:對不可變清單進行排序。 透過 List.of(...) 建立的清單不可變——呼叫 sort 會得到 UnsupportedOperationException。
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // 會丟出例外!
錯誤 №2:直接排序 Set 或 Map。 排序方法不適用於 Set 與 Map。若需要排序,請先把資料轉成清單。
錯誤 №3:不正確的物件比較。 比較時不要直接相減整數——可能發生溢位。請改用 Integer.compare 或 Comparator.comparingInt,而不是 u1.age - u2.age。
// users.sort((u1, u2) -> u1.age - u2.age); // 可以運作,但在溢位時很危險!
錯誤 №4:用 contains 來做複雜搜尋。 方法 contains 只會檢查完整相等(依 equals)。若要依部分字串或物件欄位搜尋——請使用帶條件的迴圈,或使用比較器/Stream。
GO TO FULL VERSION