2015-12-29 1 views
8

私は自分自身が、私にできるようImmutableMapを返しCollectors.toMapの変形を望む見つける:私は、このようなjust learnedことをしましたJava - ImmutableMapを返すストリームコレクタはありますか?

ImmutableMap result = list.stream().collect(MyCollectors.toImmutableMap(
    tuple -> tuple._1(), tuple -> tuple._2()); 

(この特定の例ではtupleはScalaのTuple2です)

をGuava 21でJava-8サポートが提供される方法がありますが(それは6ヶ月先です)誰もが今日これを実装する可能性のある既存のライブラリ(その他)を知っていますか?

ImmutableMapは厳密には必要なく、私が必要とする最良の選択と思われるされていません:キーで検索をし、オリジナルの繰り返し順序を保持します。不変性は常に優先されます。私は、キーマッピング機能だけでなく、値マッピング機能の両方を必要とするので

なおFluentIterable.toMap(Function)は十分ではありません。

+1

私はあなたがインターネット上で何かを見なかったことに驚いています。一般的な検索エンジンで "guava java 8 collector"を検索すると、直接Guavaプロジェクト(結果として)の結果を含む多くの直接使用可能なコードが返されます。 –

+1

この目的で 'collectingAndThen()'を提供しました。 –

+0

'ImmutableMultimap'の質問の回答は、私の直接の質問に本当に答えています。しかし、そこにある解決策や私が今Web上で見つけた解決策のどれも 'ImmutableMap'を扱うための完璧な関数群を含んでいないようです - 彼らは複製キーをマージする能力がなく、かつ/または' IllegalStateException'を投げない(コレクターによって設定された規約に従います) –

答えて

13

このコレクタに匿名クラスを書く必要はありません。あなたは代わりにCollector.ofを使用することができます。

public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
      Function<? super T, ? extends K> keyMapper, 
      Function<? super T, ? extends V> valueMapper) { 
    return Collector.of(
       ImmutableMap.Builder<K, V>::new, 
       (b, e) -> b.put(keyMapper.apply(e), valueMapper.apply(e)), 
       (b1, b2) -> b1.putAll(b2.build()), 
       ImmutableMap.Builder::build); 
} 

それとも、最初の可変マップに結果を収集気にして、不変のマップにデータをコピーしない場合、あなたはcollectingAndThenと組み合わせるビルトインtoMapコレクタを使用することができますが:

ImmutableMap<String, String> result = 
    list.stream() 
     .collect(collectingAndThen(
      toMap(
       tuple -> tuple._1(), 
       tuple -> tuple._2()), 
      ImmutableMap::copyOf)); 
+1

パーフェクト:-)私はインターフェイス自体を調べるとは思わなかった。私は間違いなく「Collector.of」形式を好んでいます。これは未知の未来の用途のユーティリティ関数になるため、後でメモリチャーンの原因を突き止めることは難しいでしょう。 –

+1

Guavaはコレクタ型を提供しています。 [ 'ImmutableList.toImmutableMap()'](https://github.com/google/guava/blob/2909a996047e575cdac02ea1c06a93a9419271cf/guava/src/com/google/common/collect/ImmutableMap.java#L65-L82)。 – Jonathan

0

私はコレクターのようなライブラリを見つけられませんでした、まだ、私は私が必要としました特定のもので私の最初の亀裂を共有していますので。ここに鐘や笛はありません! (このような取り扱いとして、あるいは重複したキーをマージする。)

改善を提案すること自由に感じなさい。

/** 
* A variant of {@link Collectors#toMap(Function, Function)} for immutable maps. 
* <p> 
* Note this variant throws {@link IllegalArgumentException} upon duplicate keys, rather than 
* {@link IllegalStateException} 
* 
* @param <T> type of the input elements 
* @param <K> output type of the key mapping function 
* @param <V> output type of the value mapping function 
* @param keyMapper a mapping function to produce keys 
* @param valueMapper a mapping function to produce values 
* 
* @return a {@code Collector} which collects elements into a {@code Map} whose keys and values 
*   are the result of applying mapping functions to the input elements 
*   
* @throws IllegalArgumentException upon duplicate keys 
*/ 
public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
     Function<? super T, ? extends K> keyMapper, 
     Function<? super T, ? extends V> valueMapper) { 
    return new Collector<T, ImmutableMap.Builder<K,V>, ImmutableMap<K,V>>() { 

     public Supplier<Builder<K, V>> supplier() { 
      return ImmutableMap.Builder::new; 
     } 

     public BiConsumer<Builder<K, V>, T> accumulator() { 
      return (builder, element) -> { 
       K key = keyMapper.apply(element); 
       V value = valueMapper.apply(element); 
       builder.put(key, value); 
      }; 
     } 

     public BinaryOperator<Builder<K, V>> combiner() { 
      return (b1, b2) -> { 
       b1.putAll(b2.build()); 
       return b1; 
      }; 
     } 

     public Function<Builder<K, V>, ImmutableMap<K, V>> finisher() { 
      return builder -> builder.build(); 
     } 

     public Set<Collector.Characteristics> characteristics() { 
      return ImmutableSet.of(); 
     } 
    }; 
} 
関連する問題