6 Şubat 2020 Perşembe

Optional Sınıfı

Giriş
Sınıf final olarak tanımlı. Ayrıca bu sınıf Serializable değil. Denersek çıktı olarak şunu alırız
Caused by: java.io.NotSerializableException: java.util.Optional
Java 8 Streamleri
Bu sınıf Stream sınıfının mesela findFirst() metodu tarafından döndürülebilir. Sınıfın boş olabilmesi ihitmaline karşı  get metodu her zaman orElseX metodlarından birisi ile birlikte kullanılmalı.

filter metodu
Optional.filter metodu yazısına taşıdım

flatMap metodu
İmzası şöyle
Optional<U> flatMap(Function<? super T,Optional<U>> mapper)
Açıklaması şöyle.
If the value is present, then it applies the provided Optional-bearing mapping function to it and it returns that result. Otherwise, it returns an empty Optional.
Örnek
Elimizde procA() ve procB() olsun. procA()'nın çıktısı Optional olsun ve procB()'ye verilsin o da yeni bir Optional dönsün
void SomeMethod() {
  procA().ifPresent(a -> {
    procB(a).ifPresent(b -> {
      // Do something
      ...
    });
  });
}
Bu kodu şöyle yaparız.
procA().flatMap(this::procB).ifPresent(b -> {
    // do something
});
veya şöyle yaparız.
B b = procA()
        .flatMap(this::procB)
        .orElseThrow(SomeException::new);

// do something with b
Örnek
Şöyle yaparız.
Optional<Employee> employee = employeeServive.getEmployee();
// Sometimes an Employee has forgotten to write an up-to-date timesheet
Optional<Timesheet> timesheet = employee.flatMap(Employee::askForCurrentTimesheet); 
// We don't want to do the heavyweight action of creating a new estimate if it will just
 be discarded
client.bill(timesheet.orElseGet(EstimatedTimesheet::new));
get metodu
Açıklaması şöyle.
If a value is present in this Optional, then it returns the value. Otherwise, it throws NoSuchElementException.
Eğer optional boş ise NoSuchElementException atar. İsminden sanki exception fırlatmaz gibi düşünülüyor ve dolayı yanılgıya sebep olabiliyor. Açıklaması şöyle
Java 8 was a huge improvement to the platform, but one of the few mistakes we made was the naming of Optional.get(), because the name just invites people to call it without calling isPresent(), undermining the whole point of using Optional in the first place. (If this was the worst mistake we made in such a big release, then we did pretty well.)
Bu metod yerine orElse(null) yapılsa daha iyi olabilir.

Optional ve Supplier get() metoduna sahip ancak farklı şeyler. Açıklaması şöyle.
An Optional<T> is an argument that may or may not be provided, a return value that may or may not be provided, or a variable that may or may not be assigned a value. If it has a value, you can use .get() to retrieve it.  .get() may throw an exception if you do something wrong, i.e., if you call it when the value is not present.

A Supplier<T> is a functional object that will provide a value (or null) on demand. Unlike an Optional<T>, it's reasonable for Supplier.get() to return a different value every time you call it. If  Supplier.get() throws an exception, it means that something went wrong in its implementation, not that the caller made a mistake.
Örnek
Şöyle yaparız.
opt.get();
Stream ile şöyle kullanırız.
List<String> stringList = Arrays.asList("...", "...", "...");
return (stringList.stream().filter(str -> ...).findFirst().get()
ifPresent metodu
İmzası şöyle
void IfPresent(Consumer<? super T> consumer)
Açıklaması şöyle.
If a value is present, then the consumer with the provided value is invoked. Otherwise, it does nothing.
Optional dolu ise belirtilen Consumer'ı çağırır.

Örnek
Elimizde şöyle bir kod olsun
if (a.isPresent())
   list.add(a.get());
Şu hale getirebiliriz.
a.ifPresent(list::add);
isEmpty metodu
Java 9 ile geliyor. Açıklaması şöyle
If a value is not present, returns trueotherwise false
Şöyle yaparız.
Optional<ResponseEntry> entry = ...;

if (entry.isEmpty()) { // !entry.isPresent in java-8
   // Do your work here
}
isPresent metodu
Boolean döner. Şöyle yaparız.
Optional<Foo> opt = ...;
if (opt.isPresent()) {
  return opt.get();
}
isPresentOrElse metodu
Optional.ifPresentOrElse metodu yazısına taşıdım


map metodu
Eğer Optional dolu ise belirtilen function sonucunu döner, boşsa Optional.empty döner. İçi şöyledir.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
  Objects.requireNonNull(mapper);
  if (!isPresent())
    return empty();
  else {
    return Optional.ofNullable(mapper.apply(value));
  }
}
Örnek
Şöyle yaparız. Optional.empty ise orElse'in sonucunu döner. 
Integer val = opt.map(f -> f.getVal()).orElse(null);
Elimizde foo,bar ve baz metodlarının ayrı ayrı null dönebildiği bir durum olsun.
return wsObject.getFoo().getBar().getBaz().getInt()
Her bir çağrının sonucunu ayrı ayrı kontrol etmek yerine şöyle yaparız.
public Optional<Integer> m(Ws wsObject) {
  return Optional.ofNullable(wsObject.getFoo()) //Optional.empty() if Foo is null
    .map(f -> f.getBar()) // transform the optional or get empty 
    .map(b -> b.getBaz())
    .map(b -> b.getInt());
    // Add this if you want to return an -1 int instead of an empty optional
    // .orElse(-1);
    // Or this if you want to throw an exception instead
    // .orElseThrow(SomeApplicationException::new);
}
Örnek

procA bir Optional dönsün. Eğer bu Optional doluysa procB()'ye geçilir. Şöyle yaparız.
Optional<ReturnOfProcB> result = procA(paramA).map(this::procB);
if(!result.isPresent()) {
    throw new IllegalStateException(); 
}
Örnek
Şöyle yaparız
String value = someFunction().map(String::toUpperCase)
  .orElse("NO VALUE");
of metodu
İmzası şöyle.
public Optional<T> or​(Supplier<? extends Optional<? extends T>> supplier)
Şöyle yaparız. Parametre null olamaz.
Foo foo = null>;
Optional.of(foo); //throws NullPointerException
ofNullable metodu
Açıklaması şöyle. null girdi bile versek Optional yaratılmasını sağlar. Böylece null kontrolü yapmak gerekmez.
Returns an Optional with a present value if the specified value is non-null, otherwise an empty  Optional
Örnek
Şöyle yaparız. Parametre null olabilir.
Foo foo = ...;
Optional<Foo> opt = Optional.ofNullable(foo); // Safe from NullPointerException
Örnek
Şöyle yaparız. Parametre null olabilir.
Optional.ofNullable(myString).isPresent()// true if not null, false if null
Örnek
Şöyle yaparız. Parametre null ise isValid false olur.
if (Optional.ofNullable(country)
            .map(Country::getCity)
            .map(City::getSchool)
            .map(School::getStudent)
            .isPresent()) {
    isValid = true;
}
or metodu
Optional.or metodu yazısına taşıdım

orElse metodu
Optional.orElse metodu yazısına taşıdım.

orElseGet metodu
Optional.orElseGet metodu yazısına taşıdım.

orElseThrow metodu 
Optional.orElseThrow metodu yazısına taşıdım.
stream netodu
Optional.stream metodu yazısına taşıdım.

Diğer
Optional ve If
Optional sayesinde if yazmaya gerek kalmıor. ifPresent(),orElseGet() metodları if/else koşullarını karşılıyor.

Eskiden şöyle yapardık
Employee employee = employeeServive.getEmployee();

if(employee!=null){
    System.out.println(employee.getId());
}
Yeni kodlarda şöyle yaparız
// Changed EmployeeServive to return an optional, no more nulls!
Optional<Employee> employee = employeeServive.getEmployee();
employee.ifPresent(e -> System.out.println(e.getId()));
Şöyle yaparız.
Optional.of(employeeService)                 // definitely have the service
        .map(EmployeeService::getEmployee)   // getEmployee() might return null
        .map(Employee::getId)                // get ID from employee if there is one
        .ifPresent(System.out::println);     // and if there is an ID, print it



Hiç yorum yok:

Yorum Gönder