3

Java 8 の関数型インターフェースを理解しようとしています。ファンクターに f() があるとします。

public class A {
    private double a;

    public A(double a_) {
        a = a_;
    }

    public void f(double[] b, double[] c, double[] d) {
        d[0] = a * (b[0] + c[0]);
    }
}

Java 8 機能インターフェースを使用して同様の構造を作成することは可能ですか?

public class B {
    public double g(Function funct, double[] b, double[] c, double[] d) {
        funct(b, c, d); //Call the functor, minor calculations
        return d[0];
    }

    public static void main(String[] args) {
        A a = new A(1);
        double[] b = {2};
        double[] c = {3};
        double[] d = {4};
        double res = g(a.f, b, c, d);
    }
}

つまり、オブジェクトの特定のメソッド (または静的メソッド) をファンクターとして使用することは可能ですか? もしそうなら、短い例を挙げていただけますか?

ファンクターは、データ メンバー (a) といくつかの追加パラメーター (b、c、d) を操作する関数の図を表します...

4

2 に答える 2

0

次の解決策を見つけました。最初に、インターフェイス IFunction が作成されます。

public interface IFunction {
   double eval(double [] a, double [] b, double [] c) ;
}

クラス A は残ります。

 public class A {
    private double a;

    public A(double a_) {a = a_;}

    public void f(double[] b, double[] c, double[] d) {
        d[0] = a * (b[0] + c[0]);
    }
 }

ただし、クラス B は関数ポインターを使用します。

public class B {

  public double g(IFunction funct, double[] b, double[] c, double[] d) {
    funct.eval(b, c, d);
    return d[0];
  }

  public static void main(String[] args) {
     A a = new A(1);
     double[] b = {2};
     double[] c = {3};
     double[] d = {4};

     double res = g(a::f, b,c, d);
 }

私はそれが役立つことを願っています...多分、より良い解決策があります:-)

于 2016-08-25T15:37:49.697 に答える
0

もう 1 つの解決策は、既存の Java 8 インターフェースを使用することです。

import static org.junit.Assert.*;
import java.io.UnsupportedEncodingException;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import org.junit.Test;

public class test {

  @Test
  public void java_functions_currying() throws UnsupportedEncodingException {
    A a = new A(1);
    Double[] b = {2d};
    Double[] c = {3d};
    Double[] d = {4d};
    double res = B.g(a::f, b, c, d);
    double res1 = B.g1(a::f1, b, c, d);

    assertEquals(5, res, .01d);
    assertEquals(5, res1, .01d);
  }

  public class A {
    private double a;

    public A(double a) {
      this.a = a;
    }

    // f has type Function<Double[], BiConsumer<Double[], Double[]>>
    // Function<T, R> where 
    // T = Double[]
    // R = BiConsumer<Double[], Double[]>
    public BiConsumer<Double[], Double[]> f(Double[] b) {
      return (c, d) -> d[0] = a * (b[0] + c[0]);
    }

    // f1 has type Function<Double[], Function<Double[], Consumer<Double[]>>>
    // Function<T, R> where 
    // T = Double[]
    // R = Function<Double[], Consumer<Double[]>>
    public Function<Double[], Consumer<Double[]>> f1(Double[] b) {
      return c -> d -> d[0] = a * (b[0] + c[0]);
    }

  }

  public static class B {
    public static double g(Function<Double[], BiConsumer<Double[], Double[]>> funct, Double[] b, Double[] c, Double[] d) {
      funct.apply(b).accept(c, d);
      return d[0];
    }

    public static double g1(Function<Double[], Function<Double[], Consumer<Double[]>>> funct, Double[] b, Double[] c, Double[] d) {
      funct.apply(b).apply(c).accept(d);
      return d[0];
    }
  }
}

メソッド f は void を返すため、Consumer クラスの使用が適切です。Consumer はパラメーターを受け取りますが、戻りません。

2つのソリューションを追加しました。最初のものは、2 つのパラメーターを受け入れる BiConsumer を使用します。

Java 8 は TriFunction または TriConsumer インターフェースを提供しませんが、これは必要ありません。実際には、BiFunction および BiConsumer インターフェースも必要なく、Function および Consumer インターフェースを介して作成できます。

BiFunction<T, U, R>      <=> Function<T Function<U, R>>
BiConsumer<T, U>         <=> Function<T, Consumer<U>
TriFunction<S, T, U, R>  <=> Function<S, Function<T, Function<T, R>>>
TriConsumer<S, T, U>     <=> Function<S, Function<T, Consumer<U>>>

カリー化を検索して、常に 1 つのパラメーターのみを受け取る関数についての詳細情報を取得しますが、まだ不足しているパラメーターを取得する関数を返します。

于 2016-08-29T10:36:59.197 に答える