Quels sont les équivalents Java de Func et Action ?
Je veux dire, au lieu d'écrire ceci tout seul:
public interface Func<TInput, TResult>
{
TResult call(TInput target) throws Exception;
}
public interface Action<T>
{
void call(T target) throws Exception;
}
Réponses:
Dans Java 8, les équivalents sont respectivement les interfaces
java.util.function.Function<T, R>
etjava.util.function.Consumer<T>
. De même,java.util.function.Predicate<T>
équivaut àSystem.Predicate<T>
. Comme mentionné ailleurs, ce sont des interfaces au lieu de délégués.Mis à part: Je m'appuie actuellement fortement sur la classe d'utilitaire suivante pour faire des choses de méthode d'extension de type 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; } }
A la différence
System.Linq.Enumerable.Where<TSource>
etSystem.Linq.Enumerable.Select<TSource, TResult>
la LINQ comme les méthodes que je présente ici ne sont pas paresseux et parcourir entièrement les collections de source avant de retourner les collections de résultats à l'appelant. Pourtant, je les trouve utiles à des fins purement syntaxiques et pourraient être rendues paresseuses si nécessaire. Donnéclass Widget { public String name() { /* ... */ } }
On peut faire ce qui suit:
List<Widget> widgets = /* ... */; Iterable<Widget> filteredWidgets = IterableUtil.where(widgets, w -> w.name().startsWith("some-prefix"));
Ce que je préfère à ce qui suit:
List<Widget> widgets = /* ... */; List<Widget> filteredWidgets = new ArrayList<Widget>(); for (Widget w : widgets) { if (w.name().startsWith("some-prefix")) { filteredWidgets.add(w); } }
la source
Function<T, R>
etConsumer<T>
, vous pouvez trouver l'ensemble complet des interfaces fonctionnelles communes que Java fournit ici .L' interface appelable est similaire à Func.
L' interface exécutable est similaire à Action.
En général, Java utilise des classes internes anonymes en remplacement des délégués C #. Par exemple, voici comment ajouter du code pour réagir à la pression d'un bouton dans l'interface graphique:
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ...//code that reacts to the action... } });
la source
L'élégance des délégués Func surchargées ( en plus du délégué vs question de classe anonyme) est qu'ils prennent en charge de 0 à 16 arguments (
Func<TResult>
,Func<T, TResult>
,Func<T1, T2, TResult>
, etc.)Malheureusement, cela est impossible en Java en raison de l'effacement de type. Les classes ne peuvent pas différer uniquement par les paramètres de type générique.
Java 8 apporte maintenant dans un zoo des noms comme
BiConsumer
pourAction<T, T2>
et, parce que Java ne permet pas d' arguments de type primitif,BiIntConsumer
. Le "zoo", cependant, n'est pas très grand et je ne connais pas de bibliothèque qui l'agrandisse. Il y avait une merveilleuse proposition pour des littéraux de type de fonction comme(int, int) => void
mais elle n'a pas été adoptée.la source
Func`1
etc. C'est juste C # qui les mappe au même nom.BiConsumer
pourAction<T, T2>
et, parce que Java ne permet pas de paramètres de type primitif,BiIntConsumer
. Il y avait une proposition pour des littéraux de type de fonction comme(int, int) => void
mais elle n'a pas été adoptée.À
Func<T>
utiliser: java.util.function.Supplier http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.htmlla source
Supplier
serait équivalent àFunc<T>
(par opposition àFunc<T1, T2>
) nonAction
. AnAction
n'accepte aucun argument et ne renvoie aucun résultat. (Les autres versions deAction
acceptent divers nombres d'arguments et ne renvoient aucun résultat.)Func<T>
Java et que je m'en souvenais à tort commeAction<T>
. OupsAction<>
: 0 entrées, 0 sorties. Au mieux avec la.andThen(...)
fonctionnalité.Action<>
avec 0 entrées et 0 sorties. Mais rappelez-vous, en Java, ce ne sont que des interfaces. Ainsi, vous pouvez créer le vôtre à utiliser.Runnable
pourAction<>
, même si ce n'est pas aussi joli à utiliser que le nouveau matériel fonctionnel Java 8.Il n'y a vraiment pas d'équivalents pour ceux-ci. Vous pouvez créer des classes internes anonymes en Java, mais il existe généralement des interfaces spécifiques plutôt que des interfaces génériques telles que Func et Action.
la source
Java n'a pas le concept de délégués. Pour une approche de contournement, veuillez consulter Un programmeur Java regarde les délégués C # :
la source
Vous pouvez utiliser java.util.Function comme ceci
Mais si vous devez l'utiliser avec plus d'un argument (comme le fait C # Func), vous devez définir votre version de FunctionalInterface comme suit
@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); }
Ensuite, vous pouvez utiliser avec la variable no d'arguments
la source
Pour les versions antérieures à Java 8
Pour les rappels de méthode en C # que j'ai utilisés comme ceci:
public void MyMethod(string par1, string par2, Action<int> callback, Action<int, string> callback2) { //Async Code callback.invoke(1); callback2.invoke(4, "str"); }
et l'appelant:
utils.MyMethod("par1", "par2", (i) => { //cb result }, (i, str) => { //cb2 result });
J'ai créé de petites classes abstraites en Java
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
La méthode Java ressemble à:
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"); }
Maintenant, en l'appelant en 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 } });
Cela fonctionne également en passant / définissant vos rappels aux classes dans lesquelles vous souhaitez les appeler, la même méthode peut également être utilisée pour créer des interfaces:
package com.example.app.interfaces; public interface MyInterface<T> { void makeDo(T obj); void makeAnotherDo(); }
la source