Taha Talha PINARLI
Yazılım Geliştirme Uzmanı

Java 17: Collections

Java 17: Collections

Java Collections, nesneleri tutmak ve manipüle etmek için tasarlanan bir frameworktür. Veri üzerinde arama, sıralama, ekleme, değiştirme, silme gibi işlemleri gerçekleştirir. Collections, birçok interface (Set, List, Queue, Deque), sınıflar (ArrayList, Vector, LinkedList, PriorityQueue, HashSet, LinkedHashSet, TreeSet) ve algoritmalar içerir.

Java 8 ile birlikte collections frameworkünde bazı iyileştirmeler yapılmıştır.

  1. comparingByKey, comparingByValue: Map’ı  kolay bir şekilde key ve value’ya göre sıralamayı sağlar.
1
2
3
4
5
Map<String, String> map = new HashMap<>();
    map.put("C", "c");
    map.put("B", "b");
    map.put("A", "a");
	List<Map.Entry<String, String>> sortedByKey = map.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList()); // A=a, B=b, C=c

     2. ForEach ile iterasyon kolaylaşmıştır. ForEachOrdered stream tarafından belirlenen sırayla iterasyon yapar. ForEach ile iterasyon yaptığımızda streamin sırasının korunacağı garanti edilmez.

1
2
3
4
5
List<String> liste = new ArrayList<String>();  
   liste.add("Tübitak");  
   liste.add("Bilgem");  
   liste.add("YTE");
   liste.forEach(System.out::println);

   forEach vs forEachOrdered

1
2
3
4
5
6
7
8
9
10
String str = "tubitak bilgem yte";

	System.out.println("forEach without using parallel\n");
	str.chars().forEach(s -> System.out.print((char) s)); // tubitak bilgem yte

	System.out.println("forEach with using parallel\n");
	str.chars().parallel().forEach(s -> System.out.print((char) s)); // ilgeytem tak btubi

	System.out.println("forEachOrdered with using parallel\n");
	str.chars().parallel().forEachOrdered(s -> System.out.print((char) s)); // tubitak bilgem yte

    3.  getOrDefault: eğer key map’te varsa değerini döndürür, yoksa default olarak verilen değeri döndürür. Böylece if/else kalabalığına gerek kalmadan kontrol sağlanmış olur.

1
2
3
4
Map<String, String> map = new HashMap<>();
    map.put("C", "c");
    String value = map.getOrDefault("B", "There is no such a key");
    System.out.println(value); // There is no such a key

   4.  replaceAll: default void replaceAll(BiFunction<K, V> function)

       Her değeri BiFunction’da verilene göre işleyip değiştirir. Tüm entryler işlenene veya metot  bir exception oluşturana kadar her entrynin değerini, o entryde verilen metodu çağırmanın sonucu oluşan değerle değiştirir. Tek bir deneme ile istenilen tüm değerleri değiştirebilir.

1
2
3
4
Map<String, String> car = new HashMap<>();
    car.put("Color", "Black");
    car.put("Model", "Mercedes");
    car.replaceAll((k, v) -> "X");  // Color: X, Model: X

  5.  putIfAbsent: map.putIfAbsent(K key, V value)

      Belirtilen key mapde mevcut değilse key/valueyu mape ekler.  Key mevcutsa bir değişiklik yapmaz.

1
2
3
4
5
6
7
Map<Integer, String> map = new HashMap<>();
   map.put(1, "Tubitak");
   map.put(2, "Bilgem");
   map.put(3, "YTE");
   map.putIfAbsent(4, "MDP"); // Map’de olmayan key ekleme Output: {1=Tubitak, 2=Bilgem, 3=YTE, 4=MDP}    

   map.putIfAbsent(3, "İltaren"); // Map’de olan keye değer atama Output: {1=Tubitak, 2=Bilgem, 3=YTE, 4=MDP}

6. remove: default boolean remove(Object key, Object value)

      Belirtilen keydeki entryi mapden kaldırır.

1
2
3
4
5
Map<Integer, String> map = new HashMap<>();
    map.put(1, "Tubitak");
    map.put(2, "Bilgem");
    map.put(3, "YTE");
	map.remove(3); // Output: {1=Tubitak, 2=Bilgem}

  7. replace: default boolean replace(K key, V oldValue, V newValue)

                     default V replace(K key, V value)

      Key’i belirtilen entrynin değerini değiştirir.

1
2
3
4
5
6
Map<Integer, String> map = new HashMap<>();
    map.put(1, "Tubitak");
    map.put(2, "Bilgem");
    map.put(3, "YTE");
    map.replace(3, "YTE", " İltaren"); //	Output: {1=Tubitak, 2=Bilgem, 3= İltaren}
	map.replace(3, "İltaren"); // Eski değerini vermeden de aynı sonuç elde edilir.

  8.  compute: Belirtilen keydeki entry için belirtilen işlemleri yapmaya yarar.

1
2
3
4
5
Map<String, Integer> map = new HashMap<>(); 
    map.put("A", 5); 
    map.put("B", 6); 
    map.compute("A", (key, val) -> (val == null) ? 1: val + 1); 
    map.compute("B", (key, val) -> (val == null) ? 1 : val + 5); // {A=6, B=11}

  9. computeIfAbsent: Belirtilen key mapde bulunmuyorsa, compute ile hesaplanan value ile birlikte mape ekler.

1
2
3
4
5
Map<String, Integer> map = new HashMap<>();
     map.put("key1", 10);
     map.put("key2", 20);
     map.put("key3", 30);
     map.computeIfAbsent("key4", k -> 25 + 15); // {key1=10, key2=20, key3=30, key4=40}

  10. computeIfPresent: Belirtilen key mapde varsa ve değeri null değilse hesaplama yapar. Eğer key yoksa bir değişiklik yapmaz.

1
2
3
4
5
6
Map<String, Integer> map = new HashMap<>();
     map.put("key1", 10);
     map.put("key2", 20);
     map.put("key3", 30);
     map.computeIfPresent("key4", (key, val) -> 25 + 15); 
     map.computeIfPresent("key3", (key, val) -> val + 10); // {key1=10, key2=20, key3=40}

  11.  merge: public V merge(K key, V value, BiFunction remappingFunction)

        Belirtilen key mapde mevcut değilse, belirtilen entryi map’e ekler. Belirtilen key zaten bir değerle ilişkilendirilmişse, eski değeri belirtilen değerle birleştirir.

1
2
3
4
5
6
7
8
9
10
11
HashMap<Integer, String> map1 = new HashMap<>(); 
    map1.put(1, "A"); 
    map1.put(2, "B"); 
    map1.put(3, "C"); 

    HashMap<Integer, String> map2 = new HashMap<>(); 
    map2.put(1, "D"); 
    map2.put(2, "E"); 
    map2.put(3, "F"); 

    map2.forEach((key, value) -> map1.merge(key,value,(v1, v2) -> v1.equalsIgnoreCase(v2) ? v1 :  v1 + ", " + v2));  // {1=A, D, 2=B, E, 3=C, F}

Java 9 ile birlikte, immutable (değişmez) list, set, map, map.entry oluşturmak kolay hale gelmiştir. Java 8 ve öncesinde Collections.unmodifiableXXX metotları kullanılıyordu ve çok detaylı oldukları için bu metotların kullanımı zordu. Java 9 aynı işlemi yapan daha kullanışlı metotlar getirmiştir.  Bu metotlar, en fazla 10 elemanı olan immutable map, list, map.entry, set oluşturmaya yarar.

  • Collectionlar immutable olarak oluşturulduğu için collectionların elemanlarını silmeye, güncellemeye yeni eleman eklemeye çalışıldığında unsupportedOperationException oluşur.
1
2
List<String> list=List.of("apple","bat");
	list.add("cat"); // UnsupportedOperationException
  • Null değer eklenmesine izin verilmez. NullPointerException oluşur.

` List list=List.of("apple",null); // NullPointerException `

  • Immutable ve elemanı olan liste, map, set, map.entry oluşturulabilir.
1
2
3
4
5
6
7
8
9
10
List<String> list1=List.of("apple","bat");

	Set<String> set1= Set.of("apple","bat");

	Map<Integer,String> map = Map.of(1, "Apple", 2, "Bat", 3, "Cat");

	Map.Entry<Integer,String> mapEntry1 = Map.entry(1,"Apple");
	Map.Entry<Integer,String> mapEntry2 = Map.entry(2,"Bat");
	Map.Entry<Integer,String> mapEntry3 = Map.entry(3,"Cat");
	Map<Integer,String> mapEntry = Map.ofEntries(mapEntry1,mapEntry2,mapEntry3);
  • Boş liste, map, set, map.entry oluşturulabilir.
1
2
3
4
5
6
7
List<String> emptyList = List.of();

	Set<String> emptySet = Set.of();

	Map<Integer,String> emptyMap = Map.of();

	Map<Integer,String> emptyEntry = Map.ofEntries();

Java 11 ile birlikte Collection frameworkü toArray metodu içerir. Collectionlardan array oluşturmaya yarar.

1
2
List liste = Arrays.asList("Tübitak", "Bilgem");
	String[] listToArray = liste.toArray(String[]::new);

Referanslar