【问题标题】:Iterate a list of query results in Java and create objects based on a key value在 Java 中迭代查询结果列表并根据键值创建对象
【发布时间】:2022-01-08 12:39:16
【问题描述】:

我执行了一个查询,得到了这个对象的结果列表:

public MyObject {
      private String key;
      private String value1;
      private Integer value2;
}

结果如下所示:

键    value1       value2
1         WWW       EEE
1         WWW       AAA
2       WWW        EEE

我想迭代这个列表并创建一个类似这样的列表,按键分组。

//first object of the list
public MyCreatedObject {
      private String key; //1
      private List<Value1> value1List; //WWW, WWW
      private List<Value2> value2List; //EEE, AAA
}

//second object of the list
public MyCreatedObject {
      private String key; //2
      private List<Value1> value1List; //WWW
      private List<Value2> value2List; //EEE
}

我尝试过使用流、迭代和一些东西,但我真的很挣扎。

谁能帮帮我?

非常感谢大家

【问题讨论】:

  • "EEE"Integer 怎么样?
  • @Bohemian 同样是Value2

标签: java dictionary java-stream


【解决方案1】:

您可以通过添加几个方法将MyCreatedObject 用作收集器:

static Collector<MyObject, ?, MyCreatedObject> collector() {
    return Collector.of(MyCreatedObject::new, MyCreatedObject::add, MyCreatedObject::merge);
}

void add(MyObject o) {
    key = o.key;
    value1List.add(o.value1);
    value2List.add(o.value2);
}

MyCreatedObject merge(MyCreatedObject other) {
    key = other.key;
    value1List.addAll(other.value1List);
    value2List.addAll(other.value2List);
    return this;
}

然后将其用作groupingBy()的下游收集器:

Map<String, MyCreatedObject> grouped = list.stream()
        .collect(Collectors.groupingBy(o -> o.key, MyCreatedObject.collector()));

Ideone Demo

或者,您可以使用toMap()add() 转换为构造函数和组:

Map<String, MyCreatedObject> grouped = list.stream()
        .collect(Collectors.toMap(o -> o.key, MyCreatedObject::new, MyCreatedObject::merge));

Ideone Demo 2

【讨论】:

    【解决方案2】:

    Collectors.toMap 与合并函数可用于构建映射 Map&lt;String, MyCreatedObject&gt;,然后将其值转换为列表,前提是提供了适当的 MyCreatedObject 的全参数构造函数:

    List<MyObject> input = ... ; // setup input data
    List<MyCreatedObject> result = new ArrayList<>(input
        .stream()
        .collect(Collectors.toMap(
            MyObject::getKey, // 
            mo -> new MyCreatedObject(
                mo.getKey(), 
                new ArrayList<>(Arrays.asList(mo.getValue1())), 
                new ArrayList<>(Arrays.asList(mo.getValue2()))
            ),
            (co1, co2) -> { // merge inner lists in MyCreatedObject
                co1.getValue1List().addAll(co2.getValue1List());
                co1.getValue2List().addAll(co2.getValue2List());
                return co1;
            }
            //, LinkedHashMap::new // optional supplier to keep insertion order
        ))
        .values()
    );
    

    【讨论】:

      【解决方案3】:

      试试这个。

      record MyObject(String key, String value1, String value2) {}
      record MyCreatedObject(String key, List<String> value1List, List<String> value2List) {}
      
      public static void main(String[] args) {
      
          List<MyObject> list = List.of(
              new MyObject("1", "WWW", "EEE"),
              new MyObject("1", "WWW", "AAA"),
              new MyObject("2", "WWW", "EEE"));
      
          Map<String, MyCreatedObject> map = new LinkedHashMap<>();
          for (MyObject obj : list) {
              MyCreatedObject c = map.computeIfAbsent(obj.key(),
                  k -> new MyCreatedObject(k, new ArrayList<>(), new ArrayList<>()));
              c.value1List().add(obj.value1());
              c.value2List().add(obj.value2());
          }
          List<MyCreatedObject> result = new ArrayList<>(map.values());
      
          for (MyCreatedObject obj : result)
              System.out.println(obj);
      }
      

      输出:

      MyCreatedObject[key=1, value1List=[WWW, WWW], value2List=[EEE, AAA]]
      MyCreatedObject[key=2, value1List=[WWW], value2List=[EEE]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-26
        • 2016-05-31
        • 1970-01-01
        • 1970-01-01
        • 2013-01-15
        • 2021-11-08
        相关资源
        最近更新 更多