web-dev-qa-db-ja.com

ストリームgroupingBy:リストの最初の要素に削減

私は_List<Valuta>_を持っています。これは(簡略化された)JSONスタイルで表すことができます。

[{codice = EUR、description = Euro、ratio = 1}、{codice = USD、description = Dollars、ratio = 1.1}]

これを_Map<String, Valuta>_に次のように変換します。

{EUR = {codice = EUR、description = Euro、ratio = 1}、USD = {codice = USD、description = Dollars、ratio = 1.1}}

私はこのワンライナーを書きました:

_getValute().stream().collect(Collectors.groupingBy(Valuta::getCodice));
_

しかし、これは必要なものの代わりに_Map<String, List<Valuta>>_を返します。

mapping()関数がうまくいくと思いますが、方法がわかりません。

27
Fabio B.

実際には、Collectors.toMapの代わりにここにCollectors.groupingBy

Map<String, Valuta> map = 
    getValute().stream()
               .collect(Collectors.toMap(Valuta::getCodice, Function.identity()));

groupingBy は、グループ化関数に基づいてストリームの要素をグループ化するために使用されます。 2グループ化関数で同じ結果になるストリーム要素は、デフォルトでListに収集されます。

toMap は、要素をMapに収集します。ここで、キーは特定のキーマッパーを適用した結果であり、値は値マッパーを適用した結果です。 toMapは、デフォルトでは、重複が発生した場合に例外をスローします。

33
Tunaki

ゲームは少し遅いですが、これを試してください:

Map<String, Valuta> map = 
    getValute().stream()
               .collect(Collectors.groupingBy(Valuta::getCodice,
                            Collectors.collectingAndThen(
                                Collectors.toList(), 
                                values -> values.get(0))));
14
Philippe

Collectors.toMap(keyMappingFunction, valueMappingFunction) を使用できます

_Map<String, Valuta> map = list
        .stream()
        .collect(Collectors.toMap(Valuta::getCodice, v -> v));
_

読みやすい場合は、_v->v_をFunction.identity()に置き換えることができます。

11
Pshemo

この質問に完全に関連しているわけではありませんが、似たようなケースは静かです。複数のパラメーターでリストをグループ化し、その後、値として異なるタイプのオブジェクトを返す必要がある場合は、この解決策を試すことができます。誰かが助けてくれることを願っています!

public Map<Integer, Map<String, ObjectTypeB>> setObjectTypeB(List<ObjectTypeA> typeAList) {

   Map<Integer, Map<String, ObjectTypeB>> map = typeAList.stream()
        .collect(groupingBy(ObjectTypeA::getId,
         groupingBy(ObjectTypeA::getDate, 
         collectingAndThen(mapping(this::getObjectTypeB,toList()),values -> values.get(0)))));    
    return map;
}

    public ObjectTypeB getObjectTypeB(ObjectTypeA typeA) {
       ObjectTypeB typeB = new ObjectTypeB();
       typeB.setUnits(typeA.getUnits());
       return typeB;
}
0
Kedar Gokhale

ここに3つの方法があります。

public class Test1 {
  static class Foo {
    public int id, targetCost, actualCost;
    public String ref;

    public Foo(int id, String ref, int actualCost, int targetCost) {

      this.id = id;
      this.targetCost = targetCost;
      this.actualCost = actualCost;
      this.ref = ref;
    }

    public int getId() {
      return id;
    }

    public void setId(int id) {
      this.id = id;
    }

    public int getTargetCost() {
      return targetCost;
    }

    public void setTargetCost(int targetCost) {
      this.targetCost = targetCost;
    }

    public int getActualCost() {
      return actualCost;
    }

    public void setActualCost(int actualCost) {
      this.actualCost = actualCost;
    }

    public String getRef() {
      return ref;
    }

    public void setRef(String ref) {
      this.ref = ref;
    }

    @Override
    public String toString() {
      return " [id=" + id + ", targetCost="
    + targetCost + ", " + "actualCost=" 
          + actualCost + ", ref=" + ref
          + "]";
    }

  }// foo

  public static void main(String[] args) {

    List<Foo> list = Arrays.asList(

        new Foo(1, "P1", 300, 400), new Foo(2, "P2", 600, 400), new Foo(3, "P3", 30, 20),
        new Foo(3, "P3", 70, 20), new Foo(1, "P1", 360, 40), new Foo(4, "P4", 320, 200),
        new Foo(4, "P4", 500, 900)

    );
    // Method 1  : 
    Map<Integer, List<Foo>> collect = list.stream()
        .collect(
            Collectors.groupingBy(
                Foo::getId, 
                Collectors.collectingAndThen(

            Collectors.toList(),

            Function.identity()

        )// andthen

        )// gr

        );
    System.out.println(collect);
    /*
    {
        1=[ [id=1, targetCost=400, actualCost=300, ref=P1],
        id=1, targetCost=40, actualCost=360, ref=P1]],

         2=[ [id=2, targetCost=400, actualCost=600, ref=P2]],

          3=[ [id=3, targetCost=20, actualCost=30, ref=P3], 
           [id=3, targetCost=20, actualCost=70, ref=P3]], 

           4=[ [id=4, targetCost=200, actualCost=320, ref=P4], 
            [id=4, targetCost=900, actualCost=500, ref=P4]]

          }
  */

    // Method 2

    Map<Integer, List<Foo>> collect2 = list.stream().collect(
        Collectors.groupingBy(
            Foo::getId, 
            Collectors.mapping(
                Function.identity(), 
                Collectors.toList())));

    System.out.println(collect2);
    /*
     {
  1=[ [id=1, targetCost=400, actualCost=300, ref=P1], 
   [id=1, targetCost=40, actualCost=360, ref=P1]],

    2=[ [id=2, targetCost=400, actualCost=600, ref=P2]],

     3=[ [id=3, targetCost=20, actualCost=30, ref=P3],
       [id=3, targetCost=20, actualCost=70, ref=P3]],

        4=[ [id=4, targetCost=200, actualCost=320, ref=P4], 
         [id=4, targetCost=900, actualCost=500, ref=P4]]

       }

*/

    // Method 3 

    // If you need to compare something the you can use Compare.comparing

     Map<Integer, List<Foo>> collect3 = list
     .stream()
     .sorted( Comparator.comparing(Foo::getId)
         .thenComparing(Foo::getActualCost)
         .thenComparing(Foo::getTargetCost)    )

     .collect(                 

    Collectors.groupingBy(ch -> ch.id)     



         );

     System.out.println(collect3);


/*
{
  1=[ [id=1, targetCost=400, actualCost=300, ref=P1],  
  [id=1, targetCost=40, actualCost=360, ref=P1]],

   2=[ [id=2, targetCost=400, actualCost=600, ref=P2]],

    3=[ [id=3, targetCost=20, actualCost=30, ref=P3], 
     [id=3, targetCost=20, actualCost=70, ref=P3]],

      4=[ [id=4, targetCost=200, actualCost=320, ref=P4], 
       [id=4, targetCost=900, actualCost=500, ref=P4]]

     }
*/


  }// main

}
0
Soudipta Dutta