Przechodzę przez kod, który używa Predicate
w Javie. Nigdy nie używałem Predicate
. Czy ktoś może poprowadzić mnie do dowolnego samouczka lub wyjaśnienia koncepcyjnego Predicate
i jego implementacji w Javie?
Predicate
Przechodzę przez kod, który używa Predicate
w Javie. Nigdy nie używałem Predicate
. Czy ktoś może poprowadzić mnie do dowolnego samouczka lub wyjaśnienia koncepcyjnego Predicate
i jego implementacji w Javie?
Predicate
Odpowiedzi:
Zakładam, że mówisz o com.google.common.base.Predicate<T>
Guava.
Z API:
Określa wartość
true
lubfalse
dla danego wejścia. Na przykładRegexPredicate
może zaimplementowaćPredicate<String>
i zwrócić wartość true dla dowolnego ciągu, który pasuje do danego wyrażenia regularnego.
Jest to w zasadzie abstrakcja OOP dla boolean
testu.
Na przykład możesz mieć metodę pomocniczą, taką jak ta:
static boolean isEven(int num) {
return (num % 2) == 0; // simple
}
Teraz, biorąc pod uwagę a List<Integer>
, możesz przetwarzać tylko liczby parzyste w ten sposób:
List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
for (int number : numbers) {
if (isEven(number)) {
process(number);
}
}
W Predicate
przypadku if
test jest wyodrębniany jako typ. Pozwala to na współdziałanie z resztą API, na przykład Iterables
, które mają wiele metod użytkowych Predicate
.
Możesz więc teraz napisać coś takiego:
Predicate<Integer> isEven = new Predicate<Integer>() {
@Override public boolean apply(Integer number) {
return (number % 2) == 0;
}
};
Iterable<Integer> evenNumbers = Iterables.filter(numbers, isEven);
for (int number : evenNumbers) {
process(number);
}
Zauważ, że teraz pętla for-each jest znacznie prostsza bez if
testu. Osiągnęliśmy wyższy poziom abtraction, definiując Iterable<Integer> evenNumbers
, filter
używając -a Predicate
.
Iterables.filter
Predicate
pozwala Iterables.filter
pełnić funkcję tzw. funkcji wyższego rzędu. Samo w sobie ma to wiele zalet. Weź List<Integer> numbers
powyższy przykład. Załóżmy, że chcemy sprawdzić, czy wszystkie liczby są dodatnie. Możemy napisać coś takiego:
static boolean isAllPositive(Iterable<Integer> numbers) {
for (Integer number : numbers) {
if (number < 0) {
return false;
}
}
return true;
}
//...
if (isAllPositive(numbers)) {
System.out.println("Yep!");
}
Za pomocą Predicate
i współpracując z pozostałymi bibliotekami możemy zamiast tego napisać:
Predicate<Integer> isPositive = new Predicate<Integer>() {
@Override public boolean apply(Integer number) {
return number > 0;
}
};
//...
if (Iterables.all(numbers, isPositive)) {
System.out.println("Yep!");
}
Miejmy nadzieję, że teraz możesz zobaczyć wartość w wyższych abstrakcji dla procedur takich jak „filtruj wszystkie elementy według podanego predykatu”, „sprawdź, czy wszystkie elementy spełniają podany predykat”, itp. Tworzą lepszy kod.
Niestety Java nie ma metod pierwszej klasy: nie można przekazywać metod do Iterables.filter
i Iterables.all
. Możesz oczywiście przekazywać obiekty w Javie. W ten sposób Predicate
typ jest zdefiniowany i zamiast tego przekazujesz obiekty implementujące ten interfejs.
Predicate<Integer>
Po co wymyślać, skoro już mamy, F<Integer, Boolean>
który robi dokładnie to samo?
Predykat to funkcja, która zwraca wartość prawda / fałsz (tj. Wartość logiczna), w przeciwieństwie do zdania, które jest wartością prawda / fałsz (tj. Wartość logiczną). W Javie nie można mieć samodzielnych funkcji, więc tworzy się predykat, tworząc interfejs dla obiektu, który reprezentuje predykat, a następnie udostępnia klasę, która implementuje ten interfejs. Przykładem interfejsu predykatu może być:
public interface Predicate<ARGTYPE>
{
public boolean evaluate(ARGTYPE arg);
}
A potem możesz mieć implementację taką jak:
public class Tautology<E> implements Predicate<E>
{
public boolean evaluate(E arg){
return true;
}
}
Aby lepiej zrozumieć koncepcję, możesz przeczytać o logice pierwszego rzędu.
Edycja
Istnieje standardowy interfejs predykatu ( java.util.function.Predicate ) zdefiniowany w Java API od wersji Java 8. Przed wersją Java 8 wygodnym może być ponowne użycie interfejsu com.google.common.base.Predicate z Guawa .
Należy również zauważyć, że od wersji Java 8 pisanie predykatów przy użyciu lambd jest znacznie prostsze. Na przykład w Javie 8 i nowszych można przejść p -> true
do funkcji zamiast definiować nazwaną podklasę Tautology, jak powyżej.
Możesz zobaczyć przykłady dokumentacji java lub przykład użycia Predicate tutaj
Zasadniczo służy do filtrowania wierszy w zestawie wyników na podstawie dowolnych określonych kryteriów i zwracania wartości true dla tych wierszy, które spełniają kryteria:
// the age column to be between 7 and 10
AgeFilter filter = new AgeFilter(7, 10, 3);
// set the filter.
resultset.beforeFirst();
resultset.setFilter(filter);
Podsumowując to, co powiedział Micheal :
Możesz użyć Predicate w następujący sposób do filtrowania kolekcji w java:
public static <T> Collection<T> filter(final Collection<T> target,
final Predicate<T> predicate) {
final Collection<T> result = new ArrayList<T>();
for (final T element : target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
jednym możliwym predykatem może być:
final Predicate<DisplayFieldDto> filterCriteria =
new Predicate<DisplayFieldDto>() {
public boolean apply(final DisplayFieldDto displayFieldDto) {
return displayFieldDto.isDisplay();
}
};
Stosowanie:
final List<DisplayFieldDto> filteredList=
(List<DisplayFieldDto>)filter(displayFieldsList, filterCriteria);
Predicate
? Coś podobnego? Coś zupełnie innego?