JavaのFuncおよびActionに相当するもの


86

JavaのFuncActionに相当するものは何ですか?

つまり、これを自分で書く代わりに:

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

回答:


96

Java 8では、同等のものはそれぞれjava.util.function.Function<T, R>java.util.function.Consumer<T>インターフェイスです。同様に、java.util.function.Predicate<T>と同等System.Predicate<T>です。他の場所で述べたように、これらはデリゲートではなくインターフェースです。

関連はさておき:私は現在、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;
  }
}

とは異なりSystem.Linq.Enumerable.Where<TSource>System.Linq.Enumerable.Select<TSource, TResult>ここで紹介するLINQのようなメソッドは怠惰ではなく、結果コレクションを呼び出し元に返す前にソースコレクションを完全にトラバースします。それでも、それらは純粋に構文上の目的に役立ち、必要に応じて怠惰にすることができます。与えられた

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

次のことができます。

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

私は次のものよりも好きです:

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

1
この質問は「Javaの同等のアクション」の現在の検索結果であり、2015年になっているため、この回答に賛成票を投じる必要があります。Java8のものは、Javaが以前のものよりもはるかに優れており、これで.netのものをほぼ模倣しています。ポイント。
ロバートC.バース2015年

1
Iterable <Widget> FilteredWidgets = IterableUtil.where(widgets、w-> w.name()。startsWith( "some-prefix"));を意味していると思います。
electricbah

1
Function<T, R>Consumer<T>に加えて、Javaが提供する一般的な関数型インターフェースの完全なセットをここで見つけることができます。
ジェームズ・

35

呼び出し可能なインターフェースはFuncに似ています。

実行可能なインターフェースはアクションに似ています。

一般に、JavaはC#デリゲートの代わりに匿名内部クラスを使用します。たとえば、これはGUIのボタン押下に反応するコードを追加する方法です。

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

13
FuncとCallableの違いは、最大16個の引数(Func <TResult>、Func <T、TResult>、Func <T1、T2、TResult>など)に対してジェネリックオーバーロードがあることです。OTOH、Callableは引数を取りません。さらに、ジェネリックスの型消去のため、C#のオーバーロードを実装することは不可能です。
Aleksandr Dubinsky 2013

6

(匿名クラスの問題で対代理人以外)オーバーロードされたFuncデリゲートの優雅さは、彼らが0〜16の引数からサポートしていることである(Func<TResult>Func<T, TResult>Func<T1, T2, TResult>、など)

残念ながら、これは型消去のためにJavaでは不可能です。クラスは、ジェネリック型パラメーターだけで異なることはできません。

Java 8では、BiConsumerforAction<T, T2>やのような名前の動物園が導入されました。これは、Javaではプリミティブ型の引数が許可されていないためBiIntConsumerです。しかし、「動物園」はそれほど大きくはなく、それを拡張する図書館を私は知りません。のような関数型リテラルの素晴らしい提案がありましたが、(int, int) => void採用されませんでした。


3
興味深いことに、CLRレベルでは、ジェネリックパラメーターの数だけが異なるクラスの名前も異なります。Func`1など。それらを同じ名前にマップするのはC#だけです。
CodesInChaos 2013

@CodesInChaosああ、とても興味深い。あまりにも悪いJavaもこのようにはしませんでした。ところで、Java 8では、BiConsumerforAction<T, T2>やのような名前の動物園が導入されました。Javaではプリミティブ型のパラメーターが許可されていないためBiIntConsumerです。のような関数型リテラルの提案がありましたが、(int, int) => void採用されませんでした。
Aleksandr Dubinsky 2014年

5

以下のためのFunc<T>使用:java.util.function.Supplier http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html


SupplierFunc<T>(ではなくFunc<T1, T2>)notと同等Actionです。アンは、Action引数を受け入れないと何も結果を返しません。(他のバージョンはActionさまざまな数の引数を受け入れ、結果を返しません。)
Servy 2016年

はい、あなたは正しいです、私の間違い。私はFunc<T>Javaを探していて、誤ってそれをとして覚えていたので、この投稿に出くわしましたAction<T>。おっと
Tim Schruben 2016年

とにかく答えは私にとって役に立ちました。Javaには次のようなものもありますかAction<>:0入力、0出力。せいぜい.andThen(...)機能性で。
Kolya Ivankov 2017年

私はAction<>、0入力と0出力のようなJavaフレームワークによって提供されるものを知りません。ただし、Javaでは、これらは単なるインターフェイスです。だから、あなたは使用するためにあなた自身を作成することができます。
Tim Schruben 2017年

あるRunnableためにAction<>、それは新しいJava 8の機能のものとして使用するほどきれいではありませんが、。
Mark KCowan18年

3

それらに相当するものは実際にはありません。Javaで匿名の内部クラスを作成できますが、FuncやActionのような一般的なインターフェースではなく、特定のインターフェースが存在する傾向があります。


3

Javaにはデリゲートの概念がありません。回避策については、JavaプログラマーがC#デリゲートを調べるを参照してください。

C#にはJavaと同様の一連の機能がありますが、いくつかの新しい興味深い機能が追加されています。委任は、メソッドをファーストクラスのオブジェクトとして扱う機能です。AC#デリゲートは、Java開発者が単一のメソッドでインターフェースを使用する場合に使用されます。この記事では、C#でのデリゲートの使用について説明し、同様の機能を実行できるJavaデリゲートオブジェクトのコードを示します。こちらからソースコードをダウンロードしてください。


3

このようにjava.util.Functionを使用できます

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

ただし、(C#Funcのように)複数の引数を指定して使用する場合は、FunctionalInterfaceのバージョンを次のように定義します。

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

次に、引数の変数なしで使用できます

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

1

Java8より古いバージョンの場合

私がこのように使用したC#のメソッドコールバックの場合:

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

そしてそれを呼び出す:

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

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メソッドは次のようになります。

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

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

これは、コールバックを呼び出したいクラスにコールバックを渡す/設定することによっても機能します。同じメソッドを使用して、インターフェイスを作成することもできます。

package com.example.app.interfaces;
public interface MyInterface<T> {
    void makeDo(T obj);
    void makeAnotherDo();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.