Predikat di Jawa


100

Saya akan melalui kode yang digunakan Predicatedi Java. Saya tidak pernah menggunakan Predicate. Dapatkah seseorang memandu saya untuk tutorial atau penjelasan konseptual apa pun Predicatedan implementasinya di Java?


4
Apakah Anda berbicara tentang Jambu biji Predicate? Sesuatu yang mirip? Sesuatu yang sama sekali lain?
poligenelubricants

2
Ada juga Apache CommonsPredicate
Dan Gravell

Jawaban:


203

Saya berasumsi yang Anda bicarakan com.google.common.base.Predicate<T>dari Jambu biji.

Dari API:

Menentukan nilai trueatau falseuntuk masukan yang diberikan. Misalnya, a RegexPredicatemight implement Predicate<String>, dan return true untuk string apa pun yang cocok dengan ekspresi reguler yang diberikan.

Ini pada dasarnya adalah abstraksi OOP untuk booleantes.

Misalnya, Anda mungkin memiliki metode pembantu seperti ini:

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

Sekarang, diberi a List<Integer>, Anda hanya dapat memproses bilangan genap seperti ini:

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

Dengan Predicate, iftes disarikan sebagai tipe. Hal ini memungkinkannya untuk beroperasi dengan API lainnya, seperti Iterables, yang memiliki banyak metode utilitas yang dibutuhkan Predicate.

Jadi, Anda sekarang dapat menulis sesuatu seperti ini:

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

Perhatikan bahwa sekarang pengulangan untuk setiap jauh lebih sederhana tanpa ifpengujian. Kita telah mencapai tingkat abstraksi yang lebih tinggi dengan mendefinisikan Iterable<Integer> evenNumbers, dengan filtermenggunakan a Predicate.

Tautan API


Pada fungsi tingkat tinggi

Predicatememungkinkan Iterables.filteruntuk berfungsi sebagai apa yang disebut fungsi tingkat tinggi. Dengan sendirinya, ini menawarkan banyak keuntungan. Ambil List<Integer> numberscontoh di atas. Misalkan kita ingin menguji apakah semua bilangan positif. Kita bisa menulis sesuatu seperti ini:

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

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

Dengan a Predicate, dan beroperasi dengan pustaka lainnya, sebagai gantinya kita dapat menulis ini:

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

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

Mudah-mudahan sekarang Anda dapat melihat nilai dalam abstraksi yang lebih tinggi untuk rutinitas seperti "filter semua elemen dengan predikat yang diberikan", "periksa apakah semua elemen memenuhi predikat yang diberikan", dll. Buat kode yang lebih baik.

Sayangnya Java tidak memiliki metode kelas satu: Anda tidak dapat meneruskan metode ke Iterables.filterdan Iterables.all. Anda tentu saja bisa menyebarkan objek di Java. Jadi, Predicatejenisnya ditentukan, dan Anda lulus objek yang mengimplementasikan antarmuka ini sebagai gantinya.

Lihat juga


4
Saya tidak mengacu pada Predikat Jambu, saya seharusnya menjelaskan pertanyaan saya. Tapi penjelasan Anda membantu saya memahami apa yang saya cari, cara logika predikat digunakan di java. Terima kasih atas penjelasan yang rumit
srikanth

@polygenelubricants, Mengapa menemukan Predicate<Integer>ketika kita sudah memiliki F<Integer, Boolean>yang melakukan hal yang sama persis?
Pacerier

Anda juga bisa melakukannya dengan cara java 8: 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

Predikat adalah fungsi yang mengembalikan nilai benar / salah (yaitu boolean), berlawanan dengan proposisi yang merupakan nilai benar / salah (yaitu boolean). Di Java, seseorang tidak dapat memiliki fungsi mandiri, sehingga seseorang membuat predikat dengan membuat antarmuka untuk objek yang mewakili predikat dan kemudian menyediakan kelas yang mengimplementasikan antarmuka tersebut. Contoh antarmuka untuk predikat mungkin adalah:

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

Dan kemudian Anda mungkin memiliki implementasi seperti:

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

Untuk mendapatkan pemahaman konseptual yang lebih baik, Anda mungkin ingin membaca tentang logika orde pertama.

Sunting
Ada antarmuka Predikat standar ( java.util.function.Predicate ) yang didefinisikan dalam Java API pada Java 8. Sebelum Java 8, Anda mungkin merasa nyaman untuk menggunakan kembali antarmuka com.google.common.base.Predicate dari Jambu biji .

Juga, perhatikan bahwa pada Java 8, jauh lebih sederhana untuk menulis predikat dengan menggunakan lambda. Misalnya, di Java 8 dan yang lebih tinggi, seseorang dapat meneruskan p -> trueke fungsi alih-alih menentukan subkelas Tautologi bernama seperti di atas.


0

Anda dapat melihat contoh java doc atau contoh penggunaan Predicate disini

Pada dasarnya ini digunakan untuk memfilter baris dalam kumpulan hasil berdasarkan kriteria tertentu yang mungkin Anda miliki dan mengembalikan nilai true untuk baris yang memenuhi kriteria Anda:

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

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

Saya mengacu pada predikat commons, bukan resultset terkait. terima kasih meskipun
srikanth

0

Menambah apa yang Micheal :

Anda dapat menggunakan Predikat sebagai berikut dalam memfilter koleksi di 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;
}

satu kemungkinan predikat adalah:

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

Pemakaian:

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

1
Bukankah hal itu pada dasarnya menggagalkan tujuannya? Alasan utama dalam memilih pendekatan fungsional adalah untuk TIDAK mengulang secara manual dan menghilangkan for. Tingkat abstraksi menjadi lebih tinggi dan lebih kuat - namun melakukan untuk secara manual mengalahkan tujuan itu dan kembali ke abstraksi tingkat rendah.
Eugen
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.