Apa padanan Java dari Func and Action ?
Maksud saya, alih-alih menulis ini sendiri:
public interface Func<TInput, TResult>
{
TResult call(TInput target) throws Exception;
}
public interface Action<T>
{
void call(T target) throws Exception;
}
Jawaban:
Di Java 8, padanannya masing- masing adalah antarmuka java.util.function.Function<T, R>dan java.util.function.Consumer<T>. Demikian pula, java.util.function.Predicate<T>setara dengan System.Predicate<T>. Seperti disebutkan di tempat lain, ini adalah antarmuka, bukan delegasi.
Selain terkait: Saat ini saya sangat bergantung pada kelas utilitas berikut untuk melakukan hal-hal metode ekstensi seperti LINQ:
abstract class IterableUtil {
public static <T> Iterable<T> where(Iterable<T> items, Predicate<T> predicate) {
ArrayList<T> result = new ArrayList<T>();
for (T item : items) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
}
public static <T, R> Iterable<R> select(Iterable<T> items, Function<T, R> func) {
ArrayList<R> result = new ArrayList<R>();
for (T item : items) {
result.add(func.apply(item));
}
return result;
}
}
Tidak seperti System.Linq.Enumerable.Where<TSource>dan System.Linq.Enumerable.Select<TSource, TResult>metode mirip LINQ yang saya sajikan di sini tidak malas dan sepenuhnya melintasi koleksi sumber sebelum mengembalikan koleksi hasil ke pemanggil. Namun, saya menganggapnya berguna untuk tujuan sintaksis murni dan dapat dibuat malas jika perlu. Diberikan
class Widget {
public String name() { /* ... */ }
}
Seseorang dapat melakukan hal berikut:
List<Widget> widgets = /* ... */;
Iterable<Widget> filteredWidgets = IterableUtil.where(widgets, w -> w.name().startsWith("some-prefix"));
Yang saya lebih suka dari yang berikut:
List<Widget> widgets = /* ... */;
List<Widget> filteredWidgets = new ArrayList<Widget>();
for (Widget w : widgets) {
if (w.name().startsWith("some-prefix")) {
filteredWidgets.add(w);
}
}
Antarmuka yang dapat dipanggil mirip dengan Func.
Antarmuka yang dapat dijalankan mirip dengan Action.
Secara umum, Java menggunakan kelas dalam anonim sebagai pengganti delegasi C #. Misalnya, ini adalah bagaimana Anda menambahkan kode untuk bereaksi terhadap penekanan tombol di GUI:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
});
Keanggunan delegasi Func yang kelebihan beban (selain delegasi vs masalah kelas anonim) adalah bahwa mereka mendukung 0-16 argumen ( Func<TResult>, Func<T, TResult>, Func<T1, T2, TResult>, dll)
Sayangnya, ini tidak mungkin di Jawa karena penghapusan tipe. Kelas tidak dapat dibedakan dengan parameter tipe generik saja.
Java 8 sekarang menghadirkan banyak nama seperti BiConsumerfor Action<T, T2>dan, karena Java tidak mengizinkan argumen tipe primitif BiIntConsumer,. "Kebun binatang", bagaimanapun, tidak terlalu besar, dan saya tidak mengetahui perpustakaan yang mengembangkannya. Ada proposal bagus untuk literal tipe fungsi seperti (int, int) => voidtetapi tidak diadopsi.
Func`1dll. Hanya C # yang memetakan mereka ke nama yang sama.
BiConsumerfor Action<T, T2>dan, karena Java tidak mengizinkan parameter tipe primitif BiIntConsumer,. Ada usulan untuk literal tipe fungsi seperti (int, int) => voiditu tetapi tidak diadopsi.
Untuk Func<T>digunakan: java.util.function.Supplier
http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html
Supplierakan sama dengan Func<T>(sebagai lawan Func<T1, T2>) tidak Action. An Actiontidak menerima argumen dan tidak mengembalikan hasil. (Versi lain dari Actionmenerima berbagai jumlah argumen dan tidak mengembalikan hasil.)
Func<T>Java dan secara keliru mengingatnya sebagai Action<T>. Ups
Action<>: 0 input, 0 output. Paling baik dengan .andThen(...)fungsionalitas.
Action<>dengan 0 input dan 0 output. Tapi ingat, di Java ini hanya antarmuka. Jadi, Anda bisa membuatnya sendiri untuk digunakan.
Runnableuntuk Action<>, meskipun tidak cukup sebagai cantik untuk digunakan sebagai baru Java 8 hal fungsional.
Java tidak memiliki konsep delegasi. Untuk pendekatan solusi, silakan lihat Pemrogram Java Melihat Delegasi C # :
Meskipun C # memiliki serangkaian kemampuan yang mirip dengan Java, C # telah menambahkan beberapa fitur baru dan menarik. Delegasi adalah kemampuan untuk memperlakukan metode sebagai objek kelas satu. AC # delegate digunakan di mana pengembang Java akan menggunakan antarmuka dengan metode tunggal. Pada artikel ini, penggunaan delegasi di C # dibahas, dan kode disajikan untuk objek Delegasi Java yang dapat melakukan fungsi serupa. Unduh kode sumbernya di sini.
Anda dapat menggunakan java.util.Fungsi seperti ini
Function<Employee, String> f0 = (e) -> e.toString();
Tetapi jika Anda akan menggunakannya dengan lebih dari satu argumen (seperti yang dilakukan C # Func), maka Anda telah menentukan versi FunctionalInterface sebagai berikut
@FunctionalInterface
public interface Func2Args<T, T1, R> {
R apply(T t, T1 t1);
}
@FunctionalInterface
public interface Func3Args<T,T1,T2,R> {
R apply(T t, T1 t1, T2 t2);
}
Kemudian Anda dapat menggunakan dengan variabel tidak ada argumen
Func2Args<Employee,Employee,String> f2 = (e, e2) -> e.toString() +
e2.toString();
Func3Args<Employee,Employee,Employee,String> f3 = (e, e2, e3) ->
e.toString() + e2.toString() + e3.toString();
Untuk versi yang lebih lama dari Java 8
Untuk metode callback di C # yang saya gunakan seperti ini:
public void MyMethod(string par1, string par2, Action<int> callback, Action<int, string> callback2)
{
//Async Code
callback.invoke(1);
callback2.invoke(4, "str");
}
dan menyebutnya:
utils.MyMethod("par1", "par2", (i) =>
{
//cb result
}, (i, str) =>
{
//cb2 result
});
Saya telah membuat kelas abstrak kecil di Jawa
package com.example.app.callbacks;
public abstract class Callback1<T> {
public void invoke(T obj) {}
}
package com.example.app.callbacks;
public abstract class Callback2<T, T2> {
public void invoke(T obj, T2 obj2) {}
}
package com.example.app.callbacks;
public abstract class Callback3<T, T2, T3> {
public void invoke(T obj, T2 obj2, T3 obj3) {}
}
...ETC
Metode Java terlihat seperti:
public void myMethod(String par1, String par2, final Callback1<int> callback, final Callback2<int, String> callback2) {
//Async Code
callback.invoke(1);
callback2.invoke(4, "str");
}
Sekarang saat memanggilnya di Java:
utils.myMethod("par1", "par2", new Callback<int>() {
@Override
public void invoke(int obj) {
super.invoke(obj);
//cb result
}
}, new Callback2<int, String>() {
@Override
public void invoke(int obj, String obj2) {
super.invoke(obj, obj2);
//cb2 result
}
});
Ini juga berfungsi dengan meneruskan / menyetel callback Anda ke kelas tempat Anda ingin memanggilnya, metode yang sama juga dapat digunakan untuk membuat Antarmuka:
package com.example.app.interfaces;
public interface MyInterface<T> {
void makeDo(T obj);
void makeAnotherDo();
}