2016-03-18 24 views
8

コレクションで複数のマッピングを実行できますか? 次のコードはコンパイルエラー:Java 8の複数のマッピング

... in Stream cannot be applied to java.util.function.Function<capture<?>,capture<?>>

private static List<?> multipleMapping(final Collection<?> collection, final List<Function<?, ?>> functions) { 
    Stream<?> stream = collection.stream(); 
    for (Function<?, ?> function : functions) { 
     stream = stream.map(function); 
    } 
    return stream.collect(Collectors.toList()); 
} 

が、私は一般的なソリューションにしたいと思います。

+1

は 'Function'sを実行します。すべてが入力と同じ型を返すか、異なる型を返すことができますか? – rgettman

+1

最大数はどれくらいですか? –

+1

最後の関数から返される型は何ですか? –

答えて

3

、その後、私はあなたドンを提案それらをリストに追加しないでください。代わりに、それらを単一の関数に構成し、その単一の関数を指定されたコレクションの各要素に適用します。

あなたmultipleMapping()方法が1つの機能を受け取ることになる。

public static <T, R> List<R> multipleMapping(
    Collection<T> collection, Function<T, R> function) { 

    return collection.stream() 
      .map(function) 
      .collect(Collectors.toList()); 
} 

その後、呼び出し元のコードでは、あなたは多くの機能で構成関数を作成(あなたがとにかくすべての機能を持つことになります)とmultipleMapping()を呼び出すことができますメソッドを呼び出します。

たとえば、私たちは候補者のリストを持っているとします

List<String> candidates = Arrays.asList(
     "Hillary", "Donald", 
     "Bernie", "Ted", "John"); 

そして、4つの機能:次のように

Function<String, Integer> f1 = String::length; 

Function<Integer, Long> f2 = i -> i * 10_000L; 

Function<Long, LocalDate> f3 = LocalDate::ofEpochDay; 

Function<LocalDate, Integer> f4 = LocalDate::getYear; 

をこれらの関数は、新しい機能を構成するために使用することができます。

Function<String, Integer> function = f1.andThen(f2).andThen(f3).andThen(f4); 

または次のようになります。

Function<String, Integer> composed = f4.compose(f3).compose(f2).compose(f1); 

さて、あなたは候補者および構成functionのリストにあなたのmultipleMapping()メソッドを呼び出すことができます。

List<Integer> scores = multipleMapping(candidates, function); 

だから我々は、明示的に新しい機能を構成することで、スコアのリストに候補者の私たちのリストを変換しています4つの異なる機能から構成され、この合成機能を各候補に適用する。

あなたは選挙に勝つだろう誰が知りたい場合、あなたは最高のスコアを持つ候補チェックすることができ、私は政治に興味を持っている誰のための練習としてそれをできるようになるが、)

+0

関数の作成がより良くなり、型の制御が維持されます。ありがとう@Federico。あなたの解決策が私の問題を解決します。 – Artur

8

問題は、一般的なワイルドカード?を使用していることに起因します。あなたが望むのは、ストリーム要素のタイプを表すパラメータ化タイプTです。その入力と同じ型を返す関数であると仮定すると、あなたが持っている可能性があり:

private static <T> List<T> multipleMapping(final Collection<T> collection, final List<Function<T, T>> functions) { 
    Stream<T> stream = collection.stream(); 
    for (Function<T, T> function : functions) { 
     stream = stream.map(function); 
    } 
    return stream.collect(Collectors.toList()); 
} 

これは罰金コンパイル:mapに与えられたマッパーはcorrecly Tを受け入れ、Tを返します。ただし、関数が入力と同じ型を返さない場合は、型安全性を保つことができず、List<Function<Object, Object>>を使用する必要があります。


私たちが代わりにFunction<T, T>UnaryOperator<T>を使用することができます注。

また、あなたがforループを回避しandThenを使用して単一の一つに、すべての機能を減らすことができる:(あなたがそれらを書き留めることができるかどうか、すなわち)あなたは、いくつかの機能を持っている場合は

private static <T> List<T> multipleMapping(final Collection<T> collection, final List<Function<T, T>> functions) { 
    return collection.stream() 
        .map(functions.stream().reduce(Function.identity(), Function::andThen)) 
        .collect(Collectors.toList()); 
} 
+0

はい、それは問題ありません。しかし、私はさまざまな機能を持っています。たとえば、A→B→C→D→TではないT – Artur

+1

@akfmb次にタイプセーフティはできません。あなたが持つことができる最高のものは 'List >'です。できるだけ一般的になりたいですか?型安全性が必要な場合は、多重オーバーロードされたメソッド 'multipleMapping(リスト、関数、関数'など)を使用することができます。 – Tunaki

+1

ストリームの外に関数を作成する必要があります。コレクションの各要素 –

関連する問題