28 Nisan 2020 Salı

ConcurrentSkipListSet Sınıfı - TreeSet Gibi Sıralıdır

Giriş
Açıklaması şöyle. Yani ConcurrentSkipListSet  aslında TreeSet gibidir.
Java Collection Framework have ConcurrentSkipListMap and ConcurrentSkipListSet which are concurrent replacement for TreeMap and TreeSet. These classes implement SortedMap and SortedSet interface respectively.
TreeSetSet Yerine List İstersek
Eğer bu sınıf yerine bir List kullanmak istersek sanırım en uygun olanı ConcurrentLinkedQueue olur

Ne Avantaj Getirir
Açıklaması şöyle. Getirdiği en büyük avantaj yazma işlemi yapılırken bir kısım reader'ların halen okumaya devam edebilmesi.
A ConcurrentSkipListSet uses the Skip List data structure and so can be updated and iterated by multiple threads concurrently without breaking without using locks. It is therefore much faster than implementing a locking regime on an ordinary Set.
SkipList Data Fazla Bellek Kullanır
SkipList'in nasıl çalıştığını gösteren bir yazı burada. Yani SkipList normal LinkedList'e göre daha fazla bellek kullanıyor. Sebebi ise balanced binary tree yapısını bir liste şeklinde tutması.

constructor
Set'e eklenecek nesnelerin Comparable arayüzünü gerçekleştirmesi gerekir.

constructor - Comparator
Comparator sayesinde nesnelerin denk olup olmadığı anlaşılır. Eğer denk değilse sıralama işlemi için yine Comparator'ın döndürdüğü değer kullanılır.
Örnek
Şöyle yaparız
ConcurrentSkipListSet<Emp> set = new ConcurrentSkipListSet(new Comparator<Emp>(){

  @Override
  public int compare(Emp o1, Emp o2) {
    ...
  }
});
Örnek
Şöyle yaparız
Set<Emp> set = new ConcurrentSkipListSet(Comparator.comparing(e -> e.empid));
add metodu
Örnek ver.

addAll metodu
Örnek ver.

iterator metodu
Açıklaması şöyle. SynchronizedRandomAccessList sınıfında olduğu gibi veriyapısını kilitlemeye gerek kalmaz.
Iterators are weakly consistent, returning elements reflecting the state of the set at some point at or since the creation of the iterator. They do not throw ConcurrentModificationException, and may proceed concurrently with other operations.
Örnek
Şöyle yaparız.
for(Foo foo : fooSet) {
  //do stuff
}
remove metodu
Örnek ver.

removeAll metodu
Örnek ver.



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";
}));