Java'da Dayanak


101

PredicateJava'da kullanılan kodun üzerinden geçiyorum . Ben hiç kullanmamış Predicate. Birisi bana herhangi bir öğretici veya kavramsal açıklamaya Predicateve onun Java'daki uygulamasına rehberlik edebilir mi?


4
Guava's hakkında mı konuşuyorsunuz Predicate? Benzer bir şey? Tamamen başka bir şey mi?
poligenel yağlayıcılar

2
Ayrıca Apache CommonsPredicate
Dan Gravell

Yanıtlar:


203

com.google.common.base.Predicate<T>Guava'dan bahsettiğinizi varsayıyorum .

API'den:

Belirli bir girdi için bir trueveya falsedeğer belirler. Örneğin, bir RegexPredicateuygulayabilir Predicate<String>ve verilen normal ifadesiyle eşleşen herhangi bir dize için true döndürebilir.

Bu aslında bir booleantest için bir OOP soyutlamasıdır .

Örneğin, aşağıdaki gibi bir yardımcı yönteminiz olabilir:

static boolean isEven(int num) {
   return (num % 2) == 0; // simple
}

Şimdi, verilen bir List<Integer>, sadece çift sayıları şu şekilde işleyebilirsiniz:

    List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    for (int number : numbers) {
        if (isEven(number)) {
            process(number);
        }
    }

İle Predicate, ifdeney türü olarak dışarı mı alınıyor. Bu, API'nin geri kalanıyla birlikte çalışmasına izin verir, örneğin Iterables, alan birçok yardımcı yöntem yöntemine sahiptir Predicate.

Böylece, şimdi şöyle bir şey yazabilirsiniz:

    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);
    }

Artık her döngü için iftest olmadan çok daha basit olduğunu unutmayın . Biz tanımlayarak abtraction daha yüksek bir seviyeye ulaşan Iterable<Integer> evenNumberstarafından, filterbir kullanma -ing Predicate.

API bağlantıları


Üst düzey işlevde

PredicateIterables.filterdaha üst düzey bir işlev olarak adlandırılan işlev görmesine izin verir . Bu kendi başına birçok avantaj sunar. List<Integer> numbersYukarıdaki örneği alın . Tüm sayıların pozitif olup olmadığını test etmek istediğimizi varsayalım. Bunun gibi bir şey yazabiliriz:

static boolean isAllPositive(Iterable<Integer> numbers) {
    for (Integer number : numbers) {
        if (number < 0) {
            return false;
        }
    }
    return true;
}

//...
if (isAllPositive(numbers)) {
    System.out.println("Yep!");
}

A ile Predicateve kütüphanelerin geri kalanıyla birlikte çalışarak, bunun yerine şunu yazabiliriz:

Predicate<Integer> isPositive = new Predicate<Integer>() {
    @Override public boolean apply(Integer number) {
        return number > 0;
    }       
};

//...
if (Iterables.all(numbers, isPositive)) {
    System.out.println("Yep!");
}

Umarım artık "tüm öğeleri verilen koşula göre filtrele", "tüm öğelerin verilen koşulu karşılayıp karşılamadığını kontrol et" gibi rutinler için daha yüksek soyutlamalarda değeri görebilirsiniz.

Maalesef Java'nın birinci sınıf yöntemleri yoktur: yöntemleriIterables.filter ve çevresine geçiremezsiniz Iterables.all. Elbette, Java'da nesnelerin etrafından dolaşabilirsiniz. Böylece, Predicatetür tanımlanır ve bunun yerine bu arabirimi uygulayan nesneleri iletirsiniz .

Ayrıca bakınız


4
Guava'nın Predicate'inden bahsetmiyordum, sorumda net olmalıydım ama açıklamanız ne aradığımı, yüklem mantığının java'da nasıl kullanıldığını anlamama yardımcı oldu. Ayrıntılı açıklama için teşekkürler
srikanth

@polygenelubricants, Predicate<Integer>Zaten F<Integer, Boolean>aynı şeyi yapan bizde neden icat edelim ?
Pacerier

Bunu java 8'in yöntemiyle de yapabilirsiniz: List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Predicate<Integer> isEven = integer -> (integer % 2) == 0; Iterable<Integer> evenNumbers = numbers.stream().filter(isEven).collect(Collectors.toList());

14

Bir yüklem, doğru / yanlış (yani boole) değeri olan bir önermenin aksine doğru / yanlış (yani boole) değeri döndüren bir işlevdir. Java'da, kişi bağımsız işlevlere sahip olamaz ve bu nedenle kişi, bir yüklemi temsil eden bir nesne için bir arabirim oluşturarak ve ardından bu arabirimi uygulayan bir sınıf sağlayarak bir yüklem oluşturur. Bir yüklem için arayüz örneği şöyle olabilir:

public interface Predicate<ARGTYPE>
{
    public boolean evaluate(ARGTYPE arg);
}

Ve sonra aşağıdaki gibi bir uygulamaya sahip olabilirsiniz:

public class Tautology<E> implements Predicate<E>
{
     public boolean evaluate(E arg){
         return true;
     }
}

Daha iyi bir kavramsal anlayış elde etmek için birinci dereceden mantık hakkında bir şeyler okumak isteyebilirsiniz.

Düzenle Java 8'den itibaren Java API'de tanımlanmış
standart bir Predicate arayüzü ( java.util.function.Predicate ) vardır. Java 8'den önce com.google.common.base.Predicate arayüzünü yeniden kullanmayı uygun bulabilirsiniz . Guava .

Ayrıca, Java 8'den itibaren, lambdalar kullanarak tahmin yazmanın çok daha kolay olduğunu unutmayın. Örneğin, Java 8 ve sonraki sürümlerde, p -> trueyukarıdaki gibi adlandırılmış bir Totoloji alt sınıfını tanımlamak yerine bir işleve geçilebilir .


0

Sen görebilirsiniz java doc örneklerini veya Yüklem kullanımının örneğini burada

Temel olarak, sonuç kümesindeki satırları sahip olabileceğiniz belirli kriterlere göre filtrelemek ve kriterlerinizi karşılayan satırlar için true değerini döndürmek için kullanılır:

 // the age column to be between 7 and 10
    AgeFilter filter = new AgeFilter(7, 10, 3);

    // set the filter.
    resultset.beforeFirst();
    resultset.setFilter(filter);

Ben Resultset ile ilgili değil, ortak koşulu kastediyordum. yine de teşekkürler
srikanth

0

Micheal'ın söylediklerine ek olarak :

Predicate'i java'daki koleksiyonları filtrelemek için aşağıdaki gibi kullanabilirsiniz:

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;
}

olası bir yüklem şu olabilir:

final Predicate<DisplayFieldDto> filterCriteria = 
                    new Predicate<DisplayFieldDto>() {
   public boolean apply(final DisplayFieldDto displayFieldDto) {
    return displayFieldDto.isDisplay();
   }
  };

Kullanım:

 final List<DisplayFieldDto> filteredList=
 (List<DisplayFieldDto>)filter(displayFieldsList, filterCriteria);

1
Bu temelde amacı bozmaz mı? İşlevsel bir yaklaşım seçmenin ana nedeni, manuel olarak yinelememek ve for'dan kurtulmaktır. Soyutlama seviyesi daha yüksek ve daha güçlü hale gelir - ancak bunun için elle yapmak bu amacı geçersiz kılar ve düşük seviyeli soyutlamaya geri döner.
Eugen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.