groupingBy etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
groupingBy etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

8 Ekim 2019 Salı

Collectors groupingBy metodu - Sadece Classifier - Map Of List Haline Getirir

Giriş
Şu satırı dahil ederiz.
import static java.util.stream.Collectors.groupingBy;
İmzası şöyle.
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) 
Açıklaması şöyle. Yani nesneyi kendi içindeki bir alana göre MultiMap (Map of List) haline getirir
Returns a Collector implementing a "group by" operation on input elements of type T, grouping elements according to a classification function, and returning the results in a Map.
groupingBy metodu - classifier yani keyMapper
Sadece keyMapper verilen groupingBy() metodunu çağırırsak Map'in ikinci parametresi her zaman List olur. List'in tipi nesnenin kendisidir. Yani bu metod bir nesneyi kendi içindeki bir alana göre çoklu bölümlere (multiple partitions) ayırmak için kullanılır.

Bu anlamda Collectors.groupingBy() ve Collectors.toMap() birbirlerinden ayrılırlar çünkü toMap() hem keyMapper hem de valueMapper nesnesi alır.

Örnek
Şöyle yaparız.
Map<A> result = list.stream()
    .collect(Collectors.groupingBy(A::getId,...))
    .values();
toMap ile şöyle yaparız.
Map<Integer, A> result = listOfA.stream()
    .collect(Collectors.toMap(A::getId, ..., ...));
Örnek
Value değerlerine göre gruplamak için şöyle yaparız.
Map<String, Integer> map = new HashMap<>();

map.put("cat", 1);
map.put("kid", 3);
map.put("girl", 3);
map.put("adult", 2);
map.put("human", 5);
map.put("dog", 2);
map.put("boy", 2);

Map<Integer, List<String>> newMap = map.keySet()
                                  .stream()
                                  .collect(Collectors.groupingBy(map::get));

System.out.println(newMap);

> {1=[cat], 2=[adult, dog, boy], 3=[kid, girl], 5=[human]}

30 Mayıs 2019 Perşembe

Collectors groupingBy metodu - Classifier + Collector - Map Of X Haline Getirir

Giriş
Şu satırı dahil ederiz.
import static java.util.stream.Collectors.groupingBy;
Yani nesneyi kendi içindeki bir alana göre 
1. MultiMap (Map of List<X>) haline getirir veya
2. Map of Aggregate haline getirir.

groupingBy metodu - classifier yani keyMapper + downstream yani Collector
downstream map'in sağ tarafındaki nesnenin ne olacağını belirtir. Metodun imzası şöyledir.
groupingBy(classifier, downstream)
Metod bir Map döner.

-Map nesnesinin key alanı classifier'ın döndürdüğü tiptir
-Value alanı ise downstream'in döndürdüğü tiptir.

Classifier key değerini döner. Böylece nesneler key değerlerine göre gruplanır. Aynı key değerine sahip nesneleri downStream'e verilir.

Böylece istenirse
1 - One To One - örneğin Map<Key,Collectors.counting()
2. One To Many Map<Key,Set<X>
3. One To Many Map<Key,List<X>

şeklinde çıktılar alınabilir.

Örnek - Aggregate
Aynı departmanda çalışan kişi sayısı şöyle bulunur. Aggregate olarak her grubu sayan Collectors.counting() kullanılıyor
Map<Department, Long> map =
    list.stream()
    .collect(Collectors.groupingBy(Employee::getDep, Collectors.counting()));
Şöyle bir çıktı alabiliriz.
Personnel: 4
Accounting: 3 
Production: 3
Örnek - Aggregate
Şöyle yaparız. Aggregate olarak her grubun uzunluğunun ortalamasını alan Collectors.averagingDouble() kullanılıyor. Grupta uzunluğu 4,5,10 olan üç string varsa ortalama 19/3 olarak alınır.
// groupingBy and averagingDouble are static imports from
// java.util.stream.Collectors
Map<Character, Double> map = Arrays.stream(str.split(" "))
  .collect(groupingBy(word -> Character.toLowerCase(word.charAt(0)),
    averagingDouble(String::length)));
Örnek -One To Many (Set)
Elimizde şöyle bir kod olsun.
List<Pair<A,B>> list = //some list of pairs ; 
Şöyle yaparız.
Map<A,Set<Pair<A,B>> m =   list.stream().collect(Collectors.groupingBy((Pair::getLeft),
  Collectors.toSet()));
Örnek - One To Many (List)
Elimizde key=value listesi olsun. Key alanına göre gruplayarak Key=List<Value> haline getirmek isteyelim
A=groupA1
A=groupA2
A=groupA3
B=groupB1
B=groupB2
Şöyle yaparız
Map<String, List<String>> res = lines.stream()
  .map(s -> Arrays.asList(s.split("=")))
  .collect(Collectors.groupingBy(s -> s.get(0),
                                 Collectors.mapping(v->v.get(1),
                                 Collectors.toList())
));
Örnek - One To Many (List)
Elimizde şöyle bir kod olsun.
List<String> locations = Arrays.asList("US:5423","US:6321","CA:1326","AU:5631");
Bunu şöyle gruplamak isteyelim.
AU = [5631]
CA = [1326]
US = [5423, 6321]
Şöyle yaparız.
Map<String, List<String>> locationMap = locations.stream()
        .map(s -> s.split(":"))
        .collect(Collectors.groupingBy(a -> a[0],
                Collectors.mapping(a -> a[1], Collectors.toList())));
Örnek - One To Many (List)
Elimizde şöyle bir kod olsun
[0] : id = "34234", team = "gools", name = "bob", type = "old"
[1] : id = "23423", team = "fool" , name = "sam", type = "new"
[2] : id = "34342", team = "gools" , name = "dan", type = "new"
Veriyi şöyle multimap haline getirmek isteyelim
gools":
       ["id": 34234, "name": "bob", "type": "old"],
       ["id": 34342, "name": "dan", "type": "new"]

"fool":
       ["id": 23423, "name": "sam", "type": "new"]
Şöyle yaparız
Map<String, List<Pojo>> teamMap = 
    daoList.stream()
           .collect(Collectors.groupingBy(GenericDAO::getTeam,
                                          Collectors.mapping (dao -> new Pojo(...),
                                                              Collectors.toList())));
Diğer
Bu groupingBy overload hali aslında şu metod ile aynıdır. Bir Map yaratılır. classifier ile key nesnesi yaratılır. key map'te yok ise yeni ArrayList yaratılır. Varsa ArrayList'e eklenir.
Map<String, List<String>> res = lines.stream()
.map(s -> Arrays.asList(s.split("=")))
.collect(HashMap::new,
 (map, item) -> map.computeIfAbsent(item.get(0), k -> new ArrayList<>()).add(item.get(1)),
  HashMap::putAll);