web-dev-qa-db-ja.com

Java 8エントリセットのストリームマップ

Mapオブジェクトの各エントリでマップ操作を実行しようとしています。

キーからプレフィックスを取り、値をあるタイプから別のタイプに変換する必要があります。私のコードはMap<String, String>から構成エントリを取得し、Map<String, AttributeType>に変換しています(AttributeTypeは単なる情報を保持するクラスです。詳細はこの質問には関係ありません。)

Java 8 Streamsを使用して思いついたのは次のとおりです。

private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
   int subLength = prefix.length();
   return input.entrySet().stream().flatMap((Map.Entry<String, Object> e) -> {
      HashMap<String, AttributeType> r = new HashMap<>();
      r.put(e.getKey().substring(subLength), AttributeType.GetByName(e.getValue()));
      return r.entrySet().stream();
   }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

インターフェースであるためMap.Entryを構築できないと、単一のエントリMapインスタンスが作成され、flatMap()が使用されます。

より良い代替手段はありますか? forループを使用してこれを行う方が良いようです:

private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
   Map<String, AttributeType> result = new HashMap<>(); 
   int subLength = prefix.length(); 
   for(Map.Entry<String, String> entry : input.entrySet()) {
      result.put(entry.getKey().substring(subLength), AttributeType.GetByName( entry.getValue()));
   }
   return result;
}

このためにStream APIを避けるべきですか?または私が逃したより良い方法がありますか?

38
Wil Selwood

「古いforループ方法」をストリームに変換するだけです:

private Map<String, String> mapConfig(Map<String, Integer> input, String prefix) {
    return input.entrySet().stream()
            .collect(Collectors.toMap(
                   entry -> entry.getKey().substring(subLength), 
                   entry -> AttributeType.GetByName(entry.getValue())));
}
86
Smutje

質問は少し古いかもしれませんが、次のように単にAbstractMap.SimpleEntry <>を使用できます。

private Map<String, AttributeType> mapConfig(
    Map<String, String> input, String prefix) {
       int subLength = prefix.length();
       return input.entrySet()
          .stream()
          .map(e -> new AbstractMap.SimpleEntry<>(
               e.getKey().substring(subLength),
               AttributeType.GetByName(e.getValue()))
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

他のペアのような値オブジェクトも機能します(ApacheCommonsペアタプルなど)。

16
Dawid Pancerz

Collectors APIの次の部分を作成してください。

<K, V> Collector<? super Map.Entry<K, V>, ?, Map<K, V>> toMap() {
  return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
}
10

AbacusUtil による短いソリューションを次に示します。

Stream.of(input).toMap(e -> e.getKey().substring(subLength), 
                       e -> AttributeType.GetByName(e.getValue()));
0
user_3380739