25 Nisan 2020 Cumartesi

Collectors collectingAndThen metodu

Giriş
Şu satırı dahil edebiliriz.
import static java.util.stream.Collectors.collectingAndThen;
Birinci parametre Collector nesnesidir. Önce kendisine birinci parametre olarak verilen collect işlemini gerçekleştirir.
Ardından ikinci parametrede verilen işlemi yani andThen anlamına gelen işi yapar.

Ne Zaman Kullanılır
Eğer bir collect() işleminden sonra tekrar stream() yaratıp ikinci bir işlemi yapmak gerekiyorsa, yani şöyle bir kod varsa, collectingAndThen() metodu kullanılabilir.
input.stream()
  .collect(groupingBy(x -> x.id()))
   .entrySet()
   .stream()
   .filter(entry -> entry.getValue().size() > 5)
   .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
Örnek
Normalde şöyle yapmak isteyelim. Yani List<Device> listesini önce List<DeviceDTO>'ya çevirmek daha sonra da bu yeni liste ile WapperDTO yaratmak isteyelim.
List<Device> devices = ...
List<DeviceDTO> devicesDTO = new ArrayList<DeviceDTO>();
for (Device d : devices) {
   devicesDTO.add(convertToDTO(d));
}

WrapperDTO wrapper = new WrapperDTO(devicesDTO);
Şöyle yaparız.
WrapperDTO wrapper = devices.stream()
    .map(d -> convertToDTO(d))
    .collect(Collectors.collectingAndThen(Collectors.toList(), WrapperDTO::new));
Örnek
Şöyle yaparız. Önce groupingBy işlemini yapar, daha sonra sonucu unmodifiable map olarak verir.
Map<String, Long> immutableSortedMap = Stream.of("b", "a", "c", "b")
  .collect(Collectors.collectingAndThen(
    Collectors.groupingBy(Function.identity(), TreeMap::new, Collectors.counting()), 
    Collections::unmodifiableMap)
);
Örnek
gropingBy + Having gibi düşünülebilir. Şöyle yaparız
Map<KeyType, List<ElementType>> result =
  input.stream()
    .collect(collectingAndThen(groupingBy(x -> x.id(), HashMap::new, toList()),
      m -> {
        m.values().removeIf(l -> l.size() <= 5);
        return m;
      }));
Bu aslında şu SQL cümlesi ile aynıdır.
GROUP BY id
HAVING COUNT(*) > 5
Örnek
Elimizde şöyle bir kod olsun. Her şeyi işledikten sonra tek bir sonuç dönmek için kullanılır.
String personWithMaxAge = persons.stream()
  .collect(Collectors.collectingAndThen(
    Collectors.maxBy(Comparator.comparing(Person::getAge)),
    (Optional<Person> p) -> p.isPresent() ? p.get().getName() : "none"
));
Şu kod ile aynıdır.
Optional<Person> p = persons.stream()
  .collect(Collectors.maxBy(Comparator.comparing(Person::getAge)));
String personWithMaxAge = p.isPresent() ? p.get().getName() : "none";
Örnek
Elimizde bir liste olsun.
List<File> files = ...
Bu listeyi ImageEntity listesine çevirip sonra tek bir listeye çevirmek için şöyle yaparız. Önce list alan bir constructor yazarız.
public ImageList(List<ImageEntity> list) {
  this.list = list;
}
Daha sonra şöyle yaparız.
ImageList imgList = files.stream()
  .map(file -> return new ImageEntity(file.getName())),     
  .collect(collectingAndThen(toList(), ImageList::new));
Örnek
Şöyle yaparız. Her şeyi işledikten sonra tek bir sonuç dönmek için kullanılır.
return values.stream()
  .map(x -> "'" + x + "'")
  .collect(Collectors.collectingAndThen(Collectors.toList(),
    list -> {
      if (list.size() == 1) {
        return "value" + list.get(0);
      }
      if (list.size() > 1) {
        return String.join(",", list);
      }
      return "Nothing found";
}));

Hiç yorum yok:

Yorum Gönder