2016-04-29 5 views
2

私は、次のよりもJavaの8を使用して、フィールド名でグループフィールド値マップを作成するには、よりエレガントな方法を見つけようとしている:のJava 8:フィールド名によってフィールド値をグループ化する

あなたが持つことができる
@Test 
public void groupFieldValuesByFieldNames() { 
    Person lawrence = aPerson().withFirstName("Lawrence").withLastName("Warren").born(); 
    Person gracie = aPerson().withFirstName("Gracie").withLastName("Ness").born(); 

    Map<String, List<String>> valuesByFieldNames = new HashMap<>(); 
    Stream.of(lawrence, gracie).forEach(person -> { 
     valuesByFieldNames.computeIfAbsent("lastName", s -> new ArrayList<>()).add(person.getLastName()); 
     valuesByFieldNames.computeIfAbsent("firstName", s -> new ArrayList<>()).add(person.getFirstName()); 
    }); 

    assertThat(valuesByFieldNames, hasEntry("lastName", asList("Warren", "Ness"))); 
    assertThat(valuesByFieldNames, hasEntry("firstName", asList("Lawrence", "Gracie"))); 
} 
+1

あなたはこのような何かをする義務を感じた場合、私は、各フィールド名をマッピングし '地図<文字列、関数<人、文字列>>'で始めたいですそのフィールドのゲッター。 –

答えて

2

これを試してください。

Map<String, List<String>> valuesByFieldNames = Stream.of(lawrence, gracie) 
    .flatMap(p -> Stream.of(new String[]{"firstName", p.getFirstName()}, 
          new String[]{"lastName", p.getLastName()})) 
    .collect(Collectors.groupingBy(a -> a[0], 
      Collectors.mapping(a -> a[1], Collectors.toList()))); 

以上の一般

Map<String, List<String>> valuesByFieldNames = Stream.of(lawrence, gracie) 
    .flatMap(p -> Stream.of(new AbstractMap.SimpleEntry<>("firstName", p.getFirstName()), 
          new AbstractMap.SimpleEntry<>("lastName", p.getLastName()))) 
    .collect(Collectors.groupingBy(e -> e.getKey(), 
      Collectors.mapping(e -> e.getValue(), Collectors.toList()))); 
2

並行して正常に動作することを、以下:

Map<String, List<String>> valuesByFieldNames = 
    Stream.of(lawrence, gracie).collect(HashMap::new, (m, p) -> { 
     m.computeIfAbsent("lastName", s -> new ArrayList<>()).add(p.getLastName()); 
     m.computeIfAbsent("firstName", s -> new ArrayList<>()).add(p.getFirstName()); 
    }, (m1, m2) -> m2.forEach((k, v) -> m1.merge(k, v, (l1, l2) -> { l1.addAll(l2); return l1; }))); 

これは何することは、mutable HashMapに一人一人を集めるということです。アキュムレータは、あなたの初期コードと同じように、computeIfAbsentを呼び出して、姓と名を計算します。コンバイナは、第2のマップのエントリを反復し、各キーを第1のマップにマージすることによって、2つのマップを併合する。競合が発生した場合、その値は2つのリストの追加になります。

関連する問題