Java’s equivalenten van Func en Action

Wat zijn Java-equivalenten van Funcen Actie?

Ik bedoel, in plaats van dit alleen te schrijven:

public interface Func<TInput, TResult>
{
    TResult call(TInput target) throws Exception;
}
public interface Action<T>
{
    void call(T target) throws Exception;
}

Antwoord 1, autoriteit 100%

In Java 8 zijn de equivalenten de java.util.function.Function<T, R>en java.util.function.Consumer<T>-interfaces. Evenzo, java.util.function.Predicate<T>is gelijk aan System.Predicate<T>. Zoals elders vermeld, zijn dit interfaces in plaats van afgevaardigden.

Aanverwant terzijde: ik leun momenteel zwaar op de volgende utility-klasse om LINQ-achtige extensiemethode-dingen te doen:

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

In tegenstelling tot System.Linq.Enumerable.Where<TSource>en System.Linq.Enumerable.Select<TSource, TResult>zijn de LINQ-achtige methoden die ik hier presenteer niet lui en de bronverzamelingen volledig doorlopen voordat de resultaatverzamelingen aan de beller worden geretourneerd. Toch vind ik ze nuttig voor puur syntactische doeleinden en kunnen ze indien nodig lui worden gemaakt. Gegeven

class Widget {
  public String name() { /* ... */ }
}

Je kunt het volgende doen:

List<Widget> widgets = /* ... */;
Iterable<Widget> filteredWidgets = IterableUtil.where(widgets, w -> w.name().startsWith("some-prefix"));

Wat ik liever heb dan het volgende:

List<Widget> widgets = /* ... */;
List<Widget> filteredWidgets = new ArrayList<Widget>();
for (Widget w : widgets) {
  if (w.name().startsWith("some-prefix")) {
    filteredWidgets.add(w);
  }
}

Antwoord 2, autoriteit 34%

Oproepbare-interface is vergelijkbaar naar Func.

Uitvoerbare-interface is vergelijkbaar met Action .

In het algemeen gebruikt Java anonieme interne klassen als vervanging voor C#-afgevaardigden.
Zo voegt u bijvoorbeeld code toe om te reageren op het indrukken van een knop in de GUI:

button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) { 
          ...//code that reacts to the action... 
      }
});

Antwoord 3, autoriteit 7%

De elegantie van de overbelaste Func-afgevaardigden (naast de kwestie van de afgevaardigde versus de anonieme klas) is dat ze 0 tot 16 argumenten ondersteunen (Func<TResult>, Func<T, TResult>, Func<T1, T2, TResult>, enz.)

Helaas is dit in Java onmogelijk vanwege het wissen van het type. Klassen kunnen niet alleen verschillen door generieke typeparameters.

Java 8 brengt nu een dierentuin met namen als BiConsumervoor Action<T, T2>en, omdat Java geen primitieve typeargumenten toestaat, BiIntConsumer. De “dierentuin” is echter niet erg groot en ik ken geen bibliotheek die deze uitbreidt. Er was een prachtig voorstel voor letterlijke functietypes zoals (int, int) => voidmaar het is niet aangenomen.


Antwoord 4, autoriteit 5%

Voor Func<T>gebruik: java.util.function.Supplier
http://docs.oracle.com/javase /8/docs/api/java/util/function/Supplier.html


Antwoord 5, autoriteit 4%

Je kunt java.util gebruiken. Functiezoals deze

Function<Employee, String> f0 = (e) -> e.toString();

Maar als u het met meer dan één argument wilt gebruiken (zoals C# Func doet), moet u uw versie van FunctionalInterface als volgt definiëren

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

Dan kunt u met variabele aantal argumenten gebruiken

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

Antwoord 6, autoriteit 3%

Daar zijn echt geen equivalenten voor. Je kunt anonieme interne klassen maken in Java, maar er zijn meestal specifieke interfaces in plaats van generieke zoals Func en Action.


Antwoord 7, autoriteit 2%

Java kent niet het concept van afgevaardigden. Zie A Java Programmer Looks at C# Delegates voor een tijdelijke oplossing. :

Hoewel C# een aantal mogelijkheden heeft
vergelijkbaar met Java, het heeft verschillende toegevoegd:
nieuwe en interessante functies.
Delegeren is het vermogen om een
methode als een eersteklas object. een C#
delegeren wordt gebruikt waar Java-ontwikkelaars
zou een interface gebruiken met een enkele
methode. In dit artikel wordt het gebruik van
gedelegeerden in C# wordt besproken, en code
wordt gepresenteerd voor een Java-afgevaardigde
object dat een soortgelijke . kan uitvoeren
functie. Download de broncode
hier.


Antwoord 8

Voor oudere versies dan Java 8

Voor methode-callbacks in C# die ik als volgt gebruikte:

public void MyMethod(string par1, string par2, Action<int> callback, Action<int, string> callback2)
{
    //Async Code 
        callback.invoke(1);
        callback2.invoke(4, "str");
}

en het noemen:

utils.MyMethod("par1", "par2", (i) =>
{
    //cb result
}, (i, str) =>
{
    //cb2 result
});

Ik heb kleine abstracte klassen gemaakt in 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

Java-methode ziet er als volgt uit:

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

Als je het nu in Java aanroept:

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

Dit werkt ook door uw callbacks door te geven/in te stellen naar de klassen waarin u ze wilt aanroepen, dezelfde methode kan ook worden gebruikt om interfaces te maken:

package com.example.app.interfaces;
public interface MyInterface<T> {
    void makeDo(T obj);
    void makeAnotherDo();
}

Antwoord 9

Sinds Java 8 kunnen Func en Action worden bereikt via Functionele Interface en Lambda Expression.

Functionele interface is een interface die maar één abstracte methode heeft.

@FunctionalInterface
interface Drawable {
    void Draw();
}

@FunctionalInterface-kenmerk is optioneel. Ondertussen is het Lambda Expression-concept hetzelfde voor C# en Java.

Hieronder zijn Java- en C#-code equivalent:

class App
{
    public static void Main(string[] args)
    {
        Action action = () => { Console.WriteLine("Printing from App class"); };
        action();
    }
}
@FunctionalInterface
interface Drawable {
    void Draw();
}
public class App {
    public static void main(String[] args) throws Exception {
        Drawable drawable = ()->System.out.println("Printing from App class");
        drawable.Draw();
    }
}

In Java zijn Func en Action vervangen door Functional Interface.

Met dit soort interface hoeft Java niet specifiek het Func- en Action-gemachtigdetype te hebben, omdat we elke interface kunnen maken die voldoet aan Func en Action (of het nu de parameters en het retourtype zijn). Bijgevolg is de code in Java iets uitgebreider dan de C#-versie.

(Dit is samengevat van https://www .byteinthesky.com/tutorials/func-and-action-equivalent-in-java/)


Antwoord 10

Als je een C#-achtergrond hebt (zoals ik) en op zoek bent naar:

public delegate TResult Func<in T1,in T2,out TResult>(T1 arg1, T2 arg2);

Kijk eens naar:

public interface BiFunction<T, U, R>

Antwoord 11

Dit is mijn werktuig met het ontbreken van Action<T…> meerdere params getypte generieke interface.

package x.y.delegate;
public class IAction {
    public interface _0 { void execute(); }
    public interface _1<T> { void execute(T p); }
    public interface _2<T1, T2> { void execute(T1 p1, T2 p2); }
    public interface _3<T1, T2, T3> { void execute(T1 p1, T2 p2, T3 p3); }
    public interface _4<T1, T2, T3, T4> { void execute(T1 p1, T2 p2, T3 p3, T4 p4); }
    public interface _5<T1, T2, T3, T4, T5> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5); }
    public interface _6<T1, T2, T3, T4, T5, T6> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6); }
    public interface _7<T1, T2, T3, T4, T5, T6, T7> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7); }
    public interface _8<T1, T2, T3, T4, T5, T6, T7, T8> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8); }
    public interface _9<T1, T2, T3, T4, T5, T6, T7, T8, T9> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9); }
    public interface _10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10); }
    public interface _11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11); }
    public interface _12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12); }
    public interface _13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13); }
    public interface _14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14); }
    public interface _15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15); }
    public interface _16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16); }
}
class DoSomething {
    public void doSm(IAction._1 ack, IAction._2 ack2) {
    }
}

Of je kunt mijn lib vinden met definities voor Action, Func, Predicate en Tuple op deze link:
https://github.com/ThinhVu/javaext
of https://jitpack.io/#ThinhVu/javaext/1.0.0

Other episodes