Powiązane na bok: Obecnie intensywnie opieram się na następującej klasie narzędziowej, aby robić rzeczy związane z rozszerzeniem podobnym do LINQ:
abstractclassIterableUtil{
publicstatic <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;
}
publicstatic <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;
}
}
W przeciwieństwie System.Linq.Enumerable.Where<TSource>i System.Linq.Enumerable.Select<TSource, TResult>LINQ-like metod przedstawiam tutaj nie są leniwi i przed powrotem zbiorów wynikowych do rozmówcy całkowicie przechodzić zbiorów źródłowych. Mimo to uważam je za przydatne do celów czysto syntaktycznych i w razie potrzeby można je rozlenić. Dany
Naprawdę musimy zagłosować na tę odpowiedź, ponieważ to pytanie jest obecnie numerem 1 w wynikach wyszukiwania dla „odpowiednika akcji w Javie”, a teraz jest rok 2015, więc Java 8 jest znacznie lepsza niż to, co Java miała wcześniej i prawie naśladuje rzeczy .net punkt.
Robert C. Barth
1
Myślę, że miałeś na myśli Iterable <Widget> filterWidgets = IterableUtil.where (widżety, w -> w.name (). StartedWith ("jakiś-prefiks"));
electricbah
1
W dodatku Function<T, R>i Consumer<T>można znaleźć pełny zestaw wspólnych interfejsów funkcjonalnych że Java zapewnia tutaj .
Ogólnie rzecz biorąc, Java używa anonimowych klas wewnętrznych jako zamiennika dla delegatów C #. Na przykład tak dodajesz kod reagujący na naciśnięcie przycisku w GUI:
button.addActionListener(new ActionListener() {
publicvoidactionPerformed(ActionEvent e){
...//code that reacts to the action...
}
});
Tym, co odróżnia Func od Callable, jest to, że istnieją ogólne przeciążenia dla maksymalnie 16 argumentów (Func <TResult>, Func <T, TResult>, Func <T1, T2, TResult> itd.). OTOH, Callable nie przyjmuje żadnych argumentów. Ponadto niemożliwe jest zaimplementowanie przeciążeń języka C # z powodu wymazywania typów w typach ogólnych.
Aleksandr Dubinsky
6
Elegancja z przeciążonych delegatów func (oprócz delegata vs anonimowej klasy emisji) jest to, że wspierają one od 0 do 16 argumentów ( Func<TResult>, Func<T, TResult>, Func<T1, T2, TResult>, itd.)
Niestety w Javie jest to niemożliwe z powodu wymazywania typów. Klasy nie mogą różnić się tylko parametrami typu ogólnego.
Java 8 teraz przynosi w zoo nazwach takich jak BiConsumerdla Action<T, T2>i, ponieważ Java nie pozwala prymitywne argumenty typu, BiIntConsumer. „Zoo” nie jest jednak zbyt duże i nie znam biblioteki, która by je powiększała. Była wspaniała propozycja dla literałów typu funkcji, (int, int) => voidale nie została przyjęta.
Co ciekawe, na poziomie CLR klasy różniące się jedynie liczbą parametrów ogólnych mają różne nazwy. Func`1itd. To tylko C #, który odwzorowuje je na tę samą nazwę.
CodesInChaos
@CodesInChaos Ahh, bardzo interesujące. Szkoda, że Java też tego nie zrobiła. Btw, Java 8 teraz przynosi w zoo nazwach takich jak BiConsumerdla Action<T, T2>i, ponieważ Java nie pozwala parametrów typu prymitywne BiIntConsumer. Pojawiła się propozycja literałów typu funkcji, (int, int) => voidale nie została ona przyjęta.
Supplierbyłoby równoważne Func<T>(w przeciwieństwie do Func<T1, T2>) nie Action. An Actionakceptuje żadnych argumentów i nie zwraca wyniku. (Inne wersje Actionakceptują różne liczby argumentów i nie zwracają żadnych wyników).
Servy
Tak, masz rację, mój błąd. Wpadłem na ten post, ponieważ szukałem Func<T>języka Java i omyłkowo zapamiętałem go jako Action<T>. Ups
Tim Schruben
I tak odpowiedź była dla mnie pomocna. Czy java ma też coś takiego Action<>: 0 wejść, 0 wyjść. Najlepiej z .andThen(...)funkcjonalnością.
Kolya Ivankov
Nie jestem świadomy niczego, co zapewnia framework Java, który jest podobny Action<>do 0 wejść i 0 wyjść. Ale pamiętaj, w Javie to tylko interfejsy. Możesz więc stworzyć własny do użytku.
Tim Schruben
Jest Runnabledla Action<>, chociaż nie jest tak ładny w użyciu, jak nowy funkcjonalny sprzęt Java 8.
Mark K Cowan
3
Naprawdę nie ma dla nich odpowiedników. Możesz tworzyć anonimowe klasy wewnętrzne w Javie, ale zazwyczaj istnieją specyficzne interfejsy, a nie takie ogólne, jak Func i Action.
Chociaż C # ma zestaw możliwości podobnych do Java, dodał kilka nowych i interesujących funkcji. Delegacja to możliwość traktowania metody jako obiektu pierwszej klasy. Delegat AC # jest używany, gdy programiści Java używaliby interfejsu z jedną metodą. W tym artykule omówiono użycie delegatów w języku C # i przedstawiono kod obiektu delegata języka Java, który może wykonywać podobną funkcję. Pobierz kod źródłowy tutaj.
Ale jeśli chcesz używać go z więcej niż jednym argumentem (tak jak robi to C # Func), musisz zdefiniować swoją wersję FunctionalInterface w następujący sposób
@FunctionalInterfacepublicinterfaceFunc2Args<T, T1, R> {
R apply(T t, T1 t1);
}
@FunctionalInterfacepublicinterfaceFunc3Args<T,T1,T2,R> {
R apply(T t, T1 t1, T2 t2);
}
publicvoidmyMethod(String par1, String par2, final Callback1<int> callback, final Callback2<int, String> callback2){
//Async Code
callback.invoke(1);
callback2.invoke(4, "str");
}
Teraz dzwoniąc w Javie:
utils.myMethod("par1", "par2", new Callback<int>() {
@Overridepublicvoidinvoke(int obj){
super.invoke(obj);
//cb result
}
}, new Callback2<int, String>() {
@Overridepublicvoidinvoke(int obj, String obj2){
super.invoke(obj, obj2);
//cb2 result
}
});
Działa to również poprzez przekazywanie / ustawianie wywołań zwrotnych do klas, w których chcesz je wywołać, ta sama metoda może być również użyta do tworzenia interfejsów:
Odpowiedzi:
W Javie 8 odpowiednikami są odpowiednio interfejsy
java.util.function.Function<T, R>
ijava.util.function.Consumer<T>
. Podobniejava.util.function.Predicate<T>
jest równoważne zSystem.Predicate<T>
. Jak wspomniano w innym miejscu, są to interfejsy zamiast delegatów.Powiązane na bok: Obecnie intensywnie opieram się na następującej klasie narzędziowej, aby robić rzeczy związane z rozszerzeniem podobnym do 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; } }
W przeciwieństwie
System.Linq.Enumerable.Where<TSource>
iSystem.Linq.Enumerable.Select<TSource, TResult>
LINQ-like metod przedstawiam tutaj nie są leniwi i przed powrotem zbiorów wynikowych do rozmówcy całkowicie przechodzić zbiorów źródłowych. Mimo to uważam je za przydatne do celów czysto syntaktycznych i w razie potrzeby można je rozlenić. Danyclass Widget { public String name() { /* ... */ } }
Można wykonać następujące czynności:
List<Widget> widgets = /* ... */; Iterable<Widget> filteredWidgets = IterableUtil.where(widgets, w -> w.name().startsWith("some-prefix"));
Które wolę od następujących:
List<Widget> widgets = /* ... */; List<Widget> filteredWidgets = new ArrayList<Widget>(); for (Widget w : widgets) { if (w.name().startsWith("some-prefix")) { filteredWidgets.add(w); } }
źródło
Function<T, R>
iConsumer<T>
można znaleźć pełny zestaw wspólnych interfejsów funkcjonalnych że Java zapewnia tutaj .Interfejs wywoływalny jest podobny do Func.
Runnable interfejs jest podobny do Action.
Ogólnie rzecz biorąc, Java używa anonimowych klas wewnętrznych jako zamiennika dla delegatów C #. Na przykład tak dodajesz kod reagujący na naciśnięcie przycisku w GUI:
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ...//code that reacts to the action... } });
źródło
Elegancja z przeciążonych delegatów func (oprócz delegata vs anonimowej klasy emisji) jest to, że wspierają one od 0 do 16 argumentów (
Func<TResult>
,Func<T, TResult>
,Func<T1, T2, TResult>
, itd.)Niestety w Javie jest to niemożliwe z powodu wymazywania typów. Klasy nie mogą różnić się tylko parametrami typu ogólnego.
Java 8 teraz przynosi w zoo nazwach takich jak
BiConsumer
dlaAction<T, T2>
i, ponieważ Java nie pozwala prymitywne argumenty typu,BiIntConsumer
. „Zoo” nie jest jednak zbyt duże i nie znam biblioteki, która by je powiększała. Była wspaniała propozycja dla literałów typu funkcji,(int, int) => void
ale nie została przyjęta.źródło
Func`1
itd. To tylko C #, który odwzorowuje je na tę samą nazwę.BiConsumer
dlaAction<T, T2>
i, ponieważ Java nie pozwala parametrów typu prymitywneBiIntConsumer
. Pojawiła się propozycja literałów typu funkcji,(int, int) => void
ale nie została ona przyjęta.Do
Func<T>
użytku: java.util.function.Supplier http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.htmlźródło
Supplier
byłoby równoważneFunc<T>
(w przeciwieństwie doFunc<T1, T2>
) nieAction
. AnAction
akceptuje żadnych argumentów i nie zwraca wyniku. (Inne wersjeAction
akceptują różne liczby argumentów i nie zwracają żadnych wyników).Func<T>
języka Java i omyłkowo zapamiętałem go jakoAction<T>
. UpsAction<>
: 0 wejść, 0 wyjść. Najlepiej z.andThen(...)
funkcjonalnością.Action<>
do 0 wejść i 0 wyjść. Ale pamiętaj, w Javie to tylko interfejsy. Możesz więc stworzyć własny do użytku.Runnable
dlaAction<>
, chociaż nie jest tak ładny w użyciu, jak nowy funkcjonalny sprzęt Java 8.Naprawdę nie ma dla nich odpowiedników. Możesz tworzyć anonimowe klasy wewnętrzne w Javie, ale zazwyczaj istnieją specyficzne interfejsy, a nie takie ogólne, jak Func i Action.
źródło
Java nie ma koncepcji delegatów. Aby zapoznać się z rozwiązaniem obejścia, zobacz A Java Programmer Looks at C # Delegates :
źródło
Możesz użyć java.util.Function w ten sposób
Ale jeśli chcesz używać go z więcej niż jednym argumentem (tak jak robi to C # Func), musisz zdefiniować swoją wersję FunctionalInterface w następujący sposób
@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); }
Następnie możesz użyć zmiennej liczba argumentów
źródło
W przypadku starszych wersji niż Java 8
Dla wywołań zwrotnych metod w C #, których użyłem w ten sposób:
public void MyMethod(string par1, string par2, Action<int> callback, Action<int, string> callback2) { //Async Code callback.invoke(1); callback2.invoke(4, "str"); }
i nazywam to:
utils.MyMethod("par1", "par2", (i) => { //cb result }, (i, str) => { //cb2 result });
Stworzyłem małe klasy abstrakcyjne w Javie
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
Metoda Java wygląda następująco:
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"); }
Teraz dzwoniąc w Javie:
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 } });
Działa to również poprzez przekazywanie / ustawianie wywołań zwrotnych do klas, w których chcesz je wywołać, ta sama metoda może być również użyta do tworzenia interfejsów:
package com.example.app.interfaces; public interface MyInterface<T> { void makeDo(T obj); void makeAnotherDo(); }
źródło