16 Nisan 2018 Pazartesi

Optional Sınıfı

Giriş
Sınıf final olarak tanımlı

Bu sınıf Stream sınıfının 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 dolu ise ve predicate true ise dolu Optional döner, aksi halde boş Optional döner.

Örnek
Şöyle yaparız
a.filter(o -> b && c).ifPresent(list::add);
flatMap metodu
Örnek
Elimizde procA() ve procB() olsun. procA()'nın çıktısı Optional 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
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
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);
isPresent metodu
Boolean döner. Şöyle yaparız.
Optional<Foo> opt = ...;
if (opt.isPresent()) {
  return opt.get();
}
isPresentOrElse metodu
Java 9 ile geliyor. İki tane lambda alır.
Örnek
Şöyle yaparız.
element.ifPresentOrElse(el -> System.out.println("Present " + el,
                        () -> System.out.println("Not present"));
Örnek
Şöyle yaparız.
public void check(String name){
  Optional.ofNullable(name)
    .ifPresentOrElse(YourClass::doSomething, YourClass::doMore);
} 
Şu kod ile aynıdır
public void check(String name) {
  if (name != null)
    doSomething(name);
  else 
    doMore();
} 
map metodu
İç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
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(); 
}
of metodu
Şö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
Java 9 ile geliyor. Şöyle yaparız.
Optional<Integer> a, b, c, d; // initialized
Optional<Integer> opOr = a.or(() -> b).or(() -> c).or(() -> d);
orElse metodu
Açıklaması şöyle
Returns the value if present otherwise, returns other.
Optional boş değilse taşıdığı değeri, boşsa belirtilen değeri döner. orElse metoduna girdi olarak metod verirsek çağrıldığını görürüz. Bu Java'nın metod çağrısından önce tüm parametreleri "eagerly evaluate" etmek istemesinden kaynaklanıyor.
Optional<Foo> opt = ...
opt.orElse(myFunc(...));
Yani orElse metod parametrelere uygun değil. Çözüm olarak şöyle yapmak gerekir.
opt.orElseGet(() -> myFunc(...));
Örnek
Şöyle yaparız.
int max = Arrays.stream(array).max ()
  .orElseThrow(() -> new IllegalArgumentException("Array is empty"));
orElseGet metodu
Optional boş değilse taşıdığı değeri, boşsa belirtilen supplier çağrısının sonucunu döner. Şöyle yaparız.
return stuff().that().returns().optional().orElseGet(() -> {
    ...
    return alternateResult;
});
orElseThrow metodu 
Java 10 ile geliyor. Supplier vermeye gerek yok. NoSuchElementException fırlatır.
Örnek
Şöyle yaparız.
Optional<Integer> anyOddInStream = Stream.of(2, 4, 6, 8)
                                         .filter(x -> x % 2 == 1)
                                         .findAny();
var current = anyOddInStream.orElseThrow(); 
orElseThrow metodu - Supplier
Örnek
Şöyle yaparız.
// exception could be replaced with any other
Integer opt = anyOddInStream.orElseThrow(
                           () -> new NoSuchElementException("No value present"));
map metodu
Eğer Optional dolu ise belirtilen function sonucunu döner, boşsa Optional.empty döner. Optional.empty ise orElse'in sonucunu döner. Şöyle yaparız.
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);
}
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