Giriş
Şu satırı dahil ederiz.
Şu satırı dahil ederiz.
import java.util.function.Predicate;
Predicate true veya false dönen bir function'dan ibaret. filter gibi metodlarda kullanılır. Şöyle düşünülebilir.
_ _ _ _ _ _ _
| |
T --> | predicate | --> boolean
|_ _ _ _ _ _ _|
Aslında true dönen function ile aynı işlevi görür. Şöyle düşünebiliriz.Predicate<String> predicateTest = (s)-> s.length() > 5;
System.out.println(predicateTest.test("Predicate"));
Function<String, Boolean> functionTest = str -> str.length()> 5;
System.out.println(functionTest.apply("Function"));
DoublePredicate, LongPredicate, IntPredicate gibi özelleşmiş arayüzler de geliyor. Primitive tipleri generic olarak zaten kullanamıyoruz. Şu kod derlenmez.Predicate<int> p; //does not compile
Ayrıca bu özelleşmiş arayüzler boxing yapmadıkları için daha iyi performans sunuyor.Filter Tasarım Örüntüsü - Filter Design Pattern
Predicate'ın esas amacı Filter Tasarm Örüntüsünü gerçekleştirmek
Predicate'ın esas amacı Filter Tasarm Örüntüsünü gerçekleştirmek
Örnek
Male ve Engineering'te çalışan kişileri görmek için şöyle yaparız
List<Employee> maleEngEmployeesUsingLambda = employees.stream().filter(employee -> Gender.MALE.equals(employee.getGender())).filter(employee -> Dept.ENG.equals(employee.getDepttName())).collect(Collectors.toList());
constructor - lamda
Dikkat edilmesi gereken nokta biz artık predicate nesnesini yaratmıyoruz. Genellikle lambda kullanıyoruz. Predicate kendi içinde iki alt kümeye ayrılıyor. Bunlar Predicate ve BiPredicate.
Örnek
Şöyle yaparız.
Şöyle yaparız.
Şöyle yaparız.
Örnek
Şöyle yaparız.
Predicate<? super List> predicate = Collection::isEmpty;
ÖrnekŞöyle yaparız.
Predicate<URL> p = u -> u.getFile().isEmpty();
ÖrnekŞöyle yaparız.
Predicate<Node> isElement = node -> node.getNodeType() == Node.ELEMENT_NODE;
BiPredicate<Node,String> hasName = (node,name) -> node.getNodeName().equals(name);
constructor - method reference
Şöyle yaparız.
and metodu aslında şuna benzer. Sanki elimizde bir Stream<Predicate> varmış ve allMatch() metodu çağrılmış gibidir. Şöyle yaparız.
İki tane Predicate nesnesini birleştirmek için şöyle yaparız.
Metodun içi şöyle. Sonuç olarak bir Predicate döner.
Şöyle yaparız.
class Case {
public boolean isEmpty() {
return true;
}
}
Predicate<Case> forNonStaticMethod = Case::isEmpty;
and metoduand metodu aslında şuna benzer. Sanki elimizde bir Stream<Predicate> varmış ve allMatch() metodu çağrılmış gibidir. Şöyle yaparız.
boolean filter(Employee employee) {
Stream<Predicate<String>> filters = Stream.of(
this::filterBasedOnConsistAge,
this::filterBasedOnConsistGender,
this::filterBasedOnConsistNationality,
this::filterBasedOnConsistHandicap
);
String employeeJSONString = employeeToString(employee);
return filters.allMatch(f -> f.test(employeeJSONString));
}
Stream yerine Predicate nesnelerini and() metodu ile birbirine bağlamak mümkün. Şöyle yaparız.Predicate<String> employeePredicate =
new FilterBasedOnConsistAge()
.and(new FilterBasedOnConsistGender())
.and(new FilterBasedOnConsistNationality())
.and(new FilterBasedOnConsistHandicap())
Örnekİki tane Predicate nesnesini birleştirmek için şöyle yaparız.
Predicate<String> both = ((Predicate<String>) Utilities::isNumeric).negate()
.and(((Predicate<String>) String::isEmpty).negate());
isEqual metoduMetodun içi şöyle. Sonuç olarak bir Predicate döner.
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
Şöyle yaparız.Predicate<Integer> predicate = Predicate.<Integer>isEqual(0).or(Predicate.isEqual(1));
negate metoduDiğer bazı örnekler burada
Örnek - Method Reference
Şöyle yaparız.
Örnek
3 şehirden herhangi birisinde yaşayanları bulmak için şöyle yaparız.
Şöyle yaparız.
Elimizde şöyle bir predicate olsun
Predicate<String> p = ((Predicate<String>) String::isEmpty).negate());
not metodu - Java 11
Örnek
Şöyle yaparız
Predicate<String> p = startWithZ = s -> s.charAt(0) == 'z';
Predicate<String> doesNotStartWithZ = Predicate
.not(startWithZ);
or metodu
3 şehirden herhangi birisinde yaşayanları bulmak için şöyle yaparız.
Predicate<Student> livesInDelhi = ...
Predicate<Student> livesInAmsterdam = ...
Predicate<Student> livesInNewYork = ...
Predicate<Student> livesInAnyOfTheseThreeCities = livesInDelhi.or(livesInAmsterdam)
.or(livesInNewYork);
ÖrnekŞöyle yaparız.
Predicate<Integer> pred21 = Predicate.isEqual(0);
Predicate<Integer> pred22 = pred21.or(Predicate.isEqual(1));
test metoduElimizde şöyle bir predicate olsun
Predicate<Integer> isGreaterThanZero = num -> num.intValue() > 0;
Şöyle yaparız.isGreaterThanZero.test( new Integer( 2 ));
Diğer
Predicate ve lambda İlişkisi
Predicate ve lambda İlişkisi
Predicate yaratmak için en kolay yöntem lambda kullanmak. Lambda özellikle bir seferlik kodlarda - throw away - kullanılır. Aynı kod farklı yerlerde de kullanılacaksa ortak bir yere taşımak gerekir.
Ortak bir yere taşınan yani method refence olarak kullanılan bir sınıfın metodunu çağırmak için SınıfAdı::MetodAdı şeklinde kodlarız.
Ortak bir yere taşınan yani method refence olarak kullanılan bir sınıfın metodunu çağırmak için SınıfAdı::MetodAdı şeklinde kodlarız.
Örnek
Şöyle yaparız
Predicate DönmekmyFinalList = myListToParse.stream()
.filter(Objects::nonNull)
.map(this::doSomething)
.collect(toList());
Bir başka örnek.public class Foo {
public static B bar(A a) {...}
}
...
useFunction(Foo::bar);
Lambda derleyici tarafından koda dönüştürülüyor.Örneğin filter metodunu kullanıyor olalım. Şöyle yazıyoruz.double average = list
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Derleyici bu kodu bizim için şu hale getiriyor.double average = list
.stream()
.filter(new Predicate<Person>(){
public boolean test(Person p){
return p.getGender() == Person.Sex.MALE;
}
})
.mapToInt(Person::getAge)
.average()
.getAsDouble();
1. Predicate kullandığı nesneyi capture eder
Predicate kullandığı nesnesiyi capture eder. Şöyle yaparız. Böylece seen map'i bir kere yaratılır.
public static <T> Predicate<T> distinctByKey(Function<? super T,Object> keyExtractor) {
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
BigDecimal totalShare = orders.stream()
.filter(distinctByKey(o -> o.getCompany().getId()))
.map(Order::getShare)
.reduce(BigDecimal.ZERO, BigDecimal::add);
2. Tekrar Kullanılabilir PredicateBu hep kafamı karıştıyor.
Örnek
Elimizde şöyle bir kod olsun
List<Foo> list = ...;
Foo nesnesinin getName() metodu olsun. Normalde şöyle yaparzFoo findByName(String name){
list.stream()
.filter((foo) -> foo.getName().equals(name)
...
}
Burada predicate lambda olarak yazıldı. Tekrar kullanılabilir predicate için şöyle yaparızclass Foo {
Predicate<Foo> findByName(String name){
return foo -> foo.getName().equals(name)
}
...
}
Şöyle yaparız.
Foo findByName(String name){
list.stream()
.filter(Foo.findByName(name))
...
}
Hiç yorum yok:
Yorum Gönder