Java 8 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Java 8 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

14 Kasım 2017 Salı

Supplier Arayüzü

Giriş
Şu satırı dahil ederiz.
import java.util.function.Supplier;
- Parametre almaz ve sonuç olarak bir nesne döner. Bu açından Callable ile aynıdır. Ancak Callable'dan farklı olarak checked exception fırlatmaz. Açıklaması şöyle
Suppliers are similar to Callable’s but they do not throw checked exceptions
- Guava'da da benzer com.google.common.base.Supplier isimli bir sınıf var. Bu sınıf ta java.util.function.Supplier arayüzünden kalıtıyor.

- Aslında supplier bir anlamda factory örüntüsü ile aynı şey.

constructor - lambda
Örnek
Tek bir nesne sağlayan bir Supplier için şöyle yaparız.
java.util.function.Supplier<String> supplier = () -> "test";
Örnek
Her seferinde farklı bir nesne sağlayan Supplier için için şöyle yaparız. Bu kod Stream'i 10 tane farkı nesne ile doldurur.
Supplier<Test> supplier = () -> new Test();
List<Test> list = Stream
            .generate(supplier)
            .limit(10)
            .collect(Collectors.toList());
System.out.println(list.size()); // 10
// Prints false, showing it really is calling the supplier
// once per iteration.
System.out.println(list.get(0) == list.get(1));
Örnek
Şöyle yaparız.
Supplier<Thread> supplier = (Supplier<Thread> & Serializable)
  ()
-> new Thread() {}; Açıklaması şöyle
The anonymous class declaration new Thread() {} and you are not in a static context, so this expression implicitly captures this.
Lambda içinde this capture edilmesin istersek şöyle yaparız.
static void write() throws Exception {
  Supplier<Thread> supplier = (Supplier<Thread> & Serializable)
    () -> new Thread() {};
  ...
}
constructor - Method Reference
Method Reference alır. Şöyle yaparız.
Supplier<Student> myStudent = Student::new;
get metodu
Şöyle yaparız.
Supplier<int[]> supplier = ...;
int[] primes = supplier.get();
Şöyle yaparız.
public class NaturalNumbers implements Supplier<Integer> {
  private int i = 0;
  public Integer get() { return ++i; }
}
Stream oluşturmak için şöyle yaparız.
Stream<Integer> s =
  Stream.generate(new NaturalNumbers());
Supplier Niçin Lazım
En en önemli avantajı nesnenin yaratılmasını ötelemesi. Açıklaması şöyle
Using a Supplier postpones the creation of the instance.
Aradaki farkı görmek için şöyle yaparız.
public void makeNewThingSometimes (T newInstance)
{
  if (someCondition) {
    this.instance = newInstance;
  }
}

public void makeNewThingSometimes (Supplier<T> supplier)
{
  if (someCondition) {
    this.instance = supplier.get();
  }
}

5 Mayıs 2016 Perşembe

Java 8 Functional Kullanımı

Giriş
Java 8 ile eklenen java.util.stream sınıfları ile functional programming yapılabilir. Bu sınıflar .Net'teki Linq sınıflarını andırıyorlar.

Functional Paketi
Java 8 Stream sınıflarını kullanabilmek için java.util.function paketi altındaki yapıları anlamak gerekir. Sebebini anlamadığım bir şekilde Java 8 her arity için bir isim kullanıyor.

Bu yapılardan önemli olanları şunlar.

Consumer : 1 parametre alır, void döner
Supplier : void alır , 1 sonuç döner
Predicate : 1 parametre alır, bool döner
Function  : 1 parametre alır ,1 sonuç döner


Şimdi bu kavramlara bakalım.

1. Consumer
Şu sınıflar var
BiConsumer

2. Supplier
Java 8 Supplier yazısına taşıdım.

3. Predicate
Java 8 Predicate yazısına taşıdım

4. Function
Şu sınıflar var

Annotationlar
@FunctionalInterface Anotasyonu yazısına taşıdım.

Ayrıca bir interface artık default olarak işaretli metodlar da sunabiliyor. Yani şöyle yapabiliyoruz.
public interface Drive {
  int getNumWheels();

  default int driveMiles(){
    return 10;
  }

  static int getColorID(){
    eturn 0;
  }
}
Eksikler
1. void alıp, void dönen Procedure gibi bir isimlendirmeyi unutmuşlar:)

2. Predicate + Function birlikte kullanımı - Yani Predicated Türevler
Function içinde bir Predicate olsun isteyelim. Eğer true ise bir sonuç, false ise başka bir sonuç dönelim. Yani şunu istiyoruz. Ama tabii Function içine Predicate vermek mümkün değil.
Predicate<Customer> IS_LEGACY_CUSTOMER = c -> c.getJoinedDate().isBefore(LocalDate.now()
  .minusYears(5));

Function<Customer, Integer> BONUS_POINTS_CALC = c -> {
  if(IS_LEGACY_CUSTOMER.test(c)) {
    return c.getDollarsSpent() * 4;
  } else {
    return c.getDollarsSpent() * 2;
  }
};
Örnek
Şöyle yaparız
public interface PredicatedFunction<T, R> extends Function<T, R> {

  static <T, R> Function<T, R> of(Function<? super T, ? extends R> f1, 
                                  Function<? super T, ? extends R> f2,
    Predicate<? super T> p) {
      return (T t) -> {
        if (p.test(t)) {
          return f1.apply(t);
        }
        return f2.apply(t);
      };
  }
}

Function<Customer, Integer> BONUS_POINTS_CALC = PredicatedFunction.of(
  c -> c.getDollarsSpent() * 4, // if true
  c -> c.getDollarsSpent() * 2, // if false
  c -> c.getJoinedDate().isBefore(LocalDate.now().minusYears(5));
Şöyle yaparız
public interface PredicatedUnaryOperator<T> extends UnaryOperator<T> {

  static <T> UnaryOperator<T> of(UnaryOperator<T> f, Predicate<? super T> p) {
    UnaryOperator<T> identity = UnaryOperator.identity();
    return (T t) -> {
      if (p.test(t)) {
        return f.apply(t);
      }
      return identity.apply(t);
    };
  }
}
Şöyle yaparız
public interface PredicatedConsumer<T> extends Consumer<T> {
  static <T> Consumer<T> of(Consumer<? super T> c, Predicate<? super T> p) {
    return (T t) -> {
      if (p.test(t)) {
        c.accept(t);
      }
    };
  }
}

Consumer<Message> NEW_MESSAGE_PROCESSOR = PredicatedConsumer.of(
  m -> processMessage(m) ,
  m -> m.getOriginationTime().isBefore(LocalDateTime.now().minusMinutes(5)));