2017-05-23 4 views
3

java 8ストリームAPIを使用してStoreオブジェクトのリストに対してアクションを実行しています。Java8でinitialised thru :: newを実行したときに、クラスコンストラクタに引数を渡す方法

Storeは、String引数とMapperオブジェクトをとります。 MapperはすべてのStoreオブジェクトで同じになります。

質問:初期化時にMapperオブジェクトを渡すには、Storeここに.map(Store::new)

public class Store { 
    public Store(String name, Mapper mapper) { 
    } 
} 

public class Mapper { 
} 

public class Test { 
    public static void main(String[] args) { 
     List<String> names = new ArrayList<String>(); 

     Mapper mapper = new Mapper(); 
     // compile time problem at Store::new because it takes 2 arguments 
     List<Store> actions = 
      names.stream() 
       .map(Store::new) 
       .collect(Collectors.toList()); 
    } 
} 
+1

以下が便利な場合があります。https://stackoverflow.com/questions/25468711/method-references-with-a-parameter また、静的メソッド参照の代わりにラムダ式を使用する方法もあります。 – thepieterdc

答えて

3

あなたは自由変数、文脈から、すなわち変数を受信する必要があるコンストラクタのメソッド参照を使用することはできません

.map(name -> new Store(name, mapper)) 
+0

答えを投稿したときにコメントではなく、疑問符を削除する必要があります... – Holger

5

代わりに、メソッド参照のラムダ式を使用します。

メソッド参照の詳細については、Java Tutorial, section Method Referencesを参照してください。

あなたが代わりにラムダ式を使用することができます。ソリューションは、より複雑かつ面倒ですが

Mapper mapper = new Mapper(); 

List<Store> actions = 
    names.stream() 
     .map(name -> new Store(name, mapper)) 
     .collect(Collectors.toList()); 

をした場合は、何らかの理由で、あなたは、あなたはまだすることができ、メソッド参照を使用して主張します。実際には、以下で紹介するハックの代わりにラムダ式を使用することは、可能な限りすべての観点から優れています。私はメソッドの参照が良いということを示すためだけに書いています。あなたがすでにシグネチャが期待どおりのメソッドまたはコンストラクタを持っている場合のみです。

public static <T, U, R> Function<T, R> bindSecond(
     BiFunction<T, U, R> biFunction, 
     U free) { 
    return t -> biFunction.apply(t, free); 
} 

ここに私が作成し、与えられたbifunction(2引数の機能)にその引数を1つしか適用する1引数の関数を返す、などされています:

は、このヘルパーメソッドを宣言すると仮定します与えられた自由変数と同様に。言い換えれば、の2番目の引数として指定されたbifunctionへの与えられた空き変数です。あなたの例では

Store::newは、実際には2つの引数(namemapper)を取り、値(新しいStoreインスタンス)を返しbifunctionで、Stream.mapがかかる1引数の機能を期待するので、あなたがそのコンパイルエラーを取得していますその唯一のパラメータとしてのストリームの要素

bindSecondヘルパーメソッドは、指定された関数と空き変数を実際にStream.mapメソッドのシグネチャと一致する1引数の関数に変換します。

次のようにあなたはそれを使用することができます。

Mapper mapper = new Mapper(); 

List<Store> actions = 
    names.stream() 
     .map(bindSecond(Store::new, mapper)) 
     .collect(Collectors.toList()); 

しかし、再び、を私は、簡単なラムダ式上で、これを使用してにはポイントを参照してくださいません。

関連する問題