1. Wyszukiwanie elementów w kolekcjach
Wyszukiwanie za pomocą standardowych metod
Gdy mamy listę, np. imion:
List<String> names = List.of("Anna", "Borys", "Wiktoria", "Anna", "Dymitr");
Java oferuje kilka wygodnych metod wyszukiwania:
- contains(Object o) – sprawdza, czy element jest w kolekcji.
- indexOf(Object o) – zwraca pierwszy indeks wystąpienia elementu (lub -1, jeśli nie znaleziono).
- lastIndexOf(Object o) – zwraca ostatni indeks wystąpienia elementu (lub -1).
Przykłady:
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("Siergiej")); // false
Fakt: Dla kolekcji typu Set nie ma metod indexOf i lastIndexOf – w Set nie ma w ogóle indeksów, tylko unikalne wartości.
Wyszukiwanie według warunku
Czasem trzeba znaleźć nie konkretną wartość, lecz element spełniający warunek. Na przykład, znaleźć pierwsze imię dłuższe niż 6 znaków. Zwykła pętla for świetnie się do tego nadaje: gdy tylko znajdziesz pasujący element – użyj break.
List<String> names = List.of("Anna", "Borys", "Wiktoria", "Anna", "Dymitr");
String found = null;
for (String name : names) {
if (name.length() > 6) {
found = name;
break; // Znaleziono pierwszy pasujący – można wyjść z pętli
}
}
System.out.println(found); // Wiktoria
Wyszukiwanie wartości maksymalnej i minimalnej
Dla kolekcji z porównywalnymi elementami (np. liczby) można szybko znaleźć maksimum i minimum za pomocą klasy 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("Maksimum: " + max);
System.out.println("Minimum: " + min);
Ważne: Elementy muszą być porównywalne (implementować Comparable), w przeciwnym razie trzeba przekazać komparator.
2. Sortowanie kolekcji
Domyślne sortowanie listy
Sortować można tylko modyfikowalne listy (np. ArrayList, LinkedList). Kolekcje typu Set i Map nie obsługują sortowania bezpośrednio.
Domyślnie sortowanie odbywa się według „naturalnego porządku”: dla liczb – rosnąco, dla łańcuchów – alfabetycznie.
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
To samo można zrobić metodą listy sort:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null oznacza: użyj naturalnego porządku
System.out.println(numbers); // [1, 3, 5, 7]
Sortowanie z komparatorem
Jeśli potrzebujesz własnej reguły – np. sortować łańcuchy po długości:
List<String> words = new ArrayList<>(List.of("kot", "słoń", "mucha", "nosorożec"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [kot, słoń, mucha, nosorożec]
W odwrotnej kolejności:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [nosorożec, mucha, słoń, kot]
Stary styl przez Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. Specyfika sortowania różnych kolekcji
Sortowanie modyfikuje tylko listę
Metody sortowania (sort, Collections.sort) działają tylko na kolekcjach, które wspierają porządek elementów (np. List). Dla Set i Map takie metody nie są przewidziane.
Próba sortowania Set:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // Błąd kompilacji: sort oczekuje List!
Jeśli chcesz uzyskać posortowaną listę z Set:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
Sortowanie Map: po kluczach i po wartościach
Sortować Map bezpośrednio się nie da, ale można:
- Uzyskać listę par „klucz–wartość”
- Posortować ją w wymagany sposób
- W razie potrzeby złożyć nową Map
Przykład: sortowanie po wartościach
Map<String, Integer> scores = Map.of(
"Anna", 15,
"Borys", 20,
"Wika", 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());
}
// Wika: 12
// Anna: 15
// Borys: 20
Sortowanie obiektów po polu
Załóżmy, że mamy klasę użytkownika:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
I listę użytkowników:
List<User> users = new ArrayList<>(List.of(
new User("Anna", 22),
new User("Borys", 18),
new User("Wika", 25)
));
Sortujemy według wieku:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Borys (18), Anna (22), Wika (25)]
W odwrotnej kolejności:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Wika (25), Anna (22), Borys (18)]
4. Typowe błędy przy wyszukiwaniu i sortowaniu kolekcji
Błąd nr 1: Sortowanie niemodyfikowalnej listy. Listy utworzone przez List.of(...) zmieniać nie wolno – przy wywołaniu sort dostaniesz UnsupportedOperationException.
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // Rzuci wyjątek!
Błąd nr 2: Sortowanie Set lub Map bezpośrednio. Metody sortowania nie działają z Set i Map. Jeśli trzeba posortować, najpierw przekształć dane w listę.
Błąd nr 3: Nieprawidłowe porównywanie obiektów. Nie odejmuj liczb całkowitych „wprost” przy porównywaniu – możliwe są przepełnienia. Zamiast u1.age - u2.age użyj Integer.compare lub Comparator.comparingInt.
// users.sort((u1, u2) -> u1.age - u2.age); // Działa, ale jest niebezpieczne przy przepełnieniu!
Błąd nr 4: Używanie contains do złożonego wyszukiwania. Metoda contains sprawdza tylko pełne dopasowanie (wg equals). Jeśli trzeba szukać po fragmencie łańcucha lub po polu obiektu – użyj pętli z warunkiem albo komparatorów/strumieni.
GO TO FULL VERSION