1. Giriş
Proqramlaşdırmada tez-tez böyük bir məlumat toplusundan yalnız lazım olan elementləri seçmək lazım gəlir — buna filtrləmə deyilir. Yalnız cüt ədədləri saxlamaq, "Java" sözünü ehtiva edən sətirləri tapmaq və ya 18 yaşdan yuxarı istifadəçiləri seçmək — bunların hamısı filtrləmə tapşırıqlarıdır.
Java-da bu cür əməliyyatlar hər addımda rast gəlinir, buna görə onları yerinə yetirməyin müxtəlif yollarına əminliklə yiyələnmək və xüsusiyyətlərini anlamaq vacibdir.
2. Dövr vasitəsilə filtrləmə
Ən əsas üsuldan başlayaq — adi for dövrəsi. Bu yanaşmaya imperativ deyilir, çünki siz açıq şəkildə nəyi və necə etmək lazım olduğunu göstərirsiniz. Oxunması rahatdır və anlamaq asandır.
Nümunə: yalnız cüt ədədləri saxlamaq
import java.util.*;
public class FilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = new ArrayList<>(); // Nəticə üçün yeni siyahı yaradırıq
for (Integer n : numbers) {
if (n % 2 == 0) { // Şərti yoxlayırıq: cüt ədəd
evenNumbers.add(n);
}
}
System.out.println("Cüt ədədlər: " + evenNumbers);
}
}
Nəticə:
Cüt ədədlər: [2, 4, 6, 8, 10]
Burada vacib məqam: ilkin kolleksiya (numbers) dəyişmir. Nəticəni yeni bir siyahıda toplayırıq.
Nümunə: sətirlərin alt sətirə görə filtrlənməsi
List<String> words = Arrays.asList("java", "python", "javascript", "kotlin", "c++");
List<String> javaWords = new ArrayList<>();
for (String word : words) {
if (word.contains("java")) {
javaWords.add(word);
}
}
System.out.println(javaWords); // [java, javascript]
Eyni prinsip: sətirlər siyahısını gəzib contains metodu ilə alt sətirin olub-olmadığını yoxlayırıq.
3. Kolleksiyadan elementlərin silinməsi: niyə hər şey bu qədər sadə deyil?
Harada tələ var?
Bəzən silərək ilkin kolleksiyadan bütün lazımsız elementləri çıxarmaq istəyirik. Lakin for-each dövründə bunu etməyə cəhd etsəniz, ConcurrentModificationException istisnası alacaqsınız.
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, -2, 3, -4, 5));
for (Integer n : numbers) {
if (n < 0) {
numbers.remove(n); // TƏHLÜKƏLİ! ConcurrentModificationException!
}
}
Nəticə:
Exception in thread "main" java.util.ConcurrentModificationException
Belə keçid zamanı kolleksiyalar onları modifikasiya etməyi “sevmir” — iterasiya pozulur.
Elementləri kolleksiyadan düzgün necə silmək olar?
Yol 1: Iterator.remove() istifadə etmək
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, -2, 3, -4, 5));
Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {
Integer n = it.next();
if (n < 0) {
it.remove(); // Təhlükəsiz şəkildə silirik!
}
}
System.out.println(numbers); // [1, 3, 5]
Burada iterator() metodu ilə iterator yaradırıq, kolleksiya boyunca hasNext() və next() ilə hərəkət edirik, lazımsız elementləri isə it.remove() çağırışı ilə silirik.
Yol 2: yalnız lazım olan elementlərlə yeni siyahı yaratmaq
List<Integer> numbers = Arrays.asList(1, -2, 3, -4, 5);
List<Integer> positive = new ArrayList<>();
for (Integer n : numbers) {
if (n >= 0) {
positive.add(n);
}
}
System.out.println(positive); // [1, 3, 5]
İlkin kolleksiyaya toxunmur və yeni siyahı yaradırıq. Yanaşma təhlükəsizdir, anlaşıqlıdır və şərtlər mürəkkəbləşdikdə asan genişlənir.
Yol 3: removeIf istifadə etmək (Java 8+)
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, -2, 3, -4, 5));
numbers.removeIf(n -> n < 0);
System.out.println(numbers); // [1, 3, 5]
Bir sətirlə şərti ötürürük: “sıfırdan kiçik olanların hamısını sil”. Təhlükəsiz modifikasiya ilə bağlı daxili detalları kolleksiya özü həll edir.
Nəticə: elementləri silmək üçün for-each istifadə etməyin. Iterator.remove(), yeni siyahı yaratmaq və ya yığcam removeIf arasında seçim edin.
4. Filtrləmə üçün hansı üsulu nə zaman istifadə etməli?
Imperativ yanaşma — adi dövr vasitəsilə — sizə təkcə elementləri seçmək yox, həm də onlarla dərhal nəsə etmək lazım olanda (məsələn, çıxışa vermək və ya çevirmək) rahatdır. Sadə və şəffafdır.
Söhbət məhz silinmədən gedirsə, for-each daxilində silməkdən qaçın. Addım-addım nəzarət üçün Iterator.remove() istifadə edin və ya müasir removeIf() — mümkün qədər qısa və ifadəli üsuldur.
Nümunə: sözlərdən ibarət siyahı var, dörd simvoldan qısa olan bütün sözləri silmək lazımdır:
List<String> words = new ArrayList<>(Arrays.asList("Java", "is", "fun", "awesome", "code"));
words.removeIf(word -> word.length() < 4);
System.out.println(words); // [Java, awesome, code]
removeIf metodu predikat qəbul edir — filtrləmə qaydası — və ona uyğun olanların hamısını silir.
5. Kolleksiyaları filtrləyərkən tipik səhvlər
Səhv №1: elementləri kolleksiyadan for-each dövründə silməyə cəhd.
Belə kod ConcurrentModificationException ilə nəticələnəcək:
for (Integer n : numbers) {
if (n < 0) {
numbers.remove(n); // BUM! ConcurrentModificationException
}
}
Düzgün variantlar: Iterator.remove() və ya removeIf istifadə edin.
Səhv №2: filtrləmə şərtinin səhv qurulması.
Yalnız mənfi ədədləri silmək lazımdır:
List<Integer> numbers = new ArrayList<>(Arrays.asList(-3, -1, 0, 2, 4));
numbers.removeIf(n -> n < 0);
System.out.println(numbers); // [0, 2, 4]
Amma səhvən “qeyri-müsbət” yazıb <= istifadə etsəniz, sıfır da yox olacaq:
numbers.removeIf(n -> n <= 0); // Nəticə: [2, 4] — sıfır səhvən silinib
Şərtlərin dəqiqliyinə diqqət edin: tək bir yanlış müqayisə nəticəni tamamilə dəyişir.
GO TO FULL VERSION