9 Ekim 2019 Çarşamba

Collectors toMap metodu - keyMapper + valueMapper - Yani Nesne İçin Key ve Value Üreterek Map Haline Getirilir

Giriş
İmzası şöyle.
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper)
Metodun içi şöyle. Yani bu metod bir HashMap döndürür.
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(
    Function<? super T, ? extends K> keyMapper, 
    Function<? super T, ? extends U> valueMapper) 
{
  return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
toMap metodunun iki parametreli hali burada
toMap metodunun üç parametreli hali burada.
toMap metodunun dört parametreli hali burada.

Yeni bir Collector döndürür. Bu Collector ise Map<K,U> döndürür. Açıklaması şöyle
It returns a Collector with as result Map<K,U> where K and U are the type of return of the two functions passed to the method.
Nesne için çağrılacak key fonksiyonunu ve value fonksiyonunu kodlarız. Bu kullanım şeklinde key fonksiyonu mevcut bir değeri - yani duplicate key - dönmemelidir. Açıklaması şöyle
If the mapped keys contains duplicates (according to Object.equals(Object), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function,Function,BinaryOperator) instead.
Exception
toMap() metoduna verilen keyMapper veya valueMapper exception fırlatabilir. Exception normal şekilde yakalanabilir. Tek problem hangi elemanın exception fırlattığını anlamak mümkün değil.

Örnek - Value Olarak Nesne
Şöyle yaparız. Key için Object.hashCode() metodunu kullandık.
Set<Foo> set = ...;
Map<Integer, Foo> map = set.stream()
                           .collect( Collectors.toMap( Object::hashCode, 
                                                       element -> element )
                                   );
Örnek - Value Olarak Nesne
Elimizde şöyle bir stream olsun. Bu map'i Map<String,Integer> yapmak isteyelim ve tek sayıları silelim istiyoruz.
Map<String, String> input = new HashMap<>();
Şöyle yaparız. Mevcut değerleri kullanmak için Map.Entry sınıfının metodlarını getter olarak kullandık.
Map<String, Integer> output =
input.entrySet().
stream().
map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), Integer.valueOf(e.getValue())))
.filter(e -> e.getValue() % 2 == 0)
.collect(Collectors.toMap(
             Map.Entry::getKey,
             Map.Entry::getValue
         ));
Örnek Value Olarak Collection
Elimizde şöyle bir kod olsun.
List<A> listofA = ...;
Şöyle yaparız. A nesnesi aynen key olarak kullanılır. repo.getListofB() metoduna A nesnesi geçilerek Collection<B> elde edilir.
Map<A, Collection<B>> resultMap = listofA.stream()
    .collect(Collectors.toMap(Function.identity(), repo::getListofB);
Örnek - Value Olarak List
Şöyle yaparız.
Map<String, List<Long>> transformInput(Map<String, List<String>> input) {
  try {
    return input.entrySet()
      .stream()
      .collect(Collectors.toMap(...,...);
  } catch (NumberFormatException nfe) {
    // log the cause
    return Collections.emptyMap();
  }
}
Örnek
Map<String, String[]> nesnesi Map<String, List<String>> olarak çevirmek için şöyle yaparız
Map<String, List<String>> result = request.getParameterMap()
  .entrySet()
  .stream()
  .collect(Collectors.toMap(Map.Entry::getKey, entry -> Arrays.asList(entry.getValue())));

Hiç yorum yok:

Yorum Gönder