【问题标题】:How to use group-1 result key1 in group-2 when use Java Lambda like Map<key1, Map<key2, List<Obj>>>使用 Java Lambda(如 Map<key1, Map<key2, List<Obj>>>)时如何在 group-2 中使用 group-1 结果 key1
【发布时间】:2019-05-08 11:46:44
【问题描述】:

Java Lambda 如何使用 group-1 生成 group-2。

这个问题是我解决的问题的更新: How to covert List to Map<T, <K, List<Person>>> use java lambda?

你可以看到最后的代码。 function key2 想使用 function key1 的结果,怎么办?

class Person{
   int age;
   int cityCode;
   String name;
}

method:

// Map<age, Map<cityCode, List<Person>>>
public Map<Integer, Map<Integer, List<Person>>> covertListToMap(List<Person> list){

      // TODO: How to make List<Person> to Map<age, Map<cityCode, List<Person>>>

}



Function<Person, Integer> key1 = (Person p) -> {
            // do many sth then get a key1Result:
            int key1Result = p.getAge() * new Random(10).nextInt();
            return key1Result;
        };


Function<Person, Integer> key2 = (Person p) -> {
            //  Question: how to get and use Function key1 key1Result:

            int key1Result = 0;

            int result = p.getCityCode() + key1Result;
            return result;
        };

Map<Integer, Map<Integer, List<Person>>> collect = list.stream().collect(groupingBy(key1, groupingBy(key2)));

我写错了样例来说明我的意思:

Map<Integer, Map<Integer, List<Person>>> collect = list.stream().collect(groupingBy((Person p) -> {
            int key1Result = p.getAge() * new Random(10).nextInt();
            return key1Result;  // perhaps, now, key1Result is 10
        }, groupingBy((Person p) -> {

            // now, I want to get the key1Result which is 10, How to do it?  
            int key1Result = 0;

            int result = p.getCityCode() + key1Result;
            return result;
        })));

【问题讨论】:

  • 当你说Key2想使用key1的结果是什么意思?你能举个例子吗?
  • int key1Result = key1.apply(person)???
  • 我更新我的问题以解释我在第三个代码区域的含义
  • 也许不是嵌套 groupBys,而是尝试链接它们。
  • 这里真正的问题是数组映射的映射

标签: java lambda


【解决方案1】:

您可以使用函数apply(T t)。根据javadoc

将此函数应用于给定参数。

在你的情况下,这意味着:

int key1Result = key1.apply(p)

编辑:当你修改你的问题时,我添加了一个答案,如果我理解你想要做什么应该是正确的:

AtomicInteger atomicInteger = new AtomicInteger(0);
Map<Integer, Map<Integer, List<Person>>> collect = personList.stream().collect(Collectors
        .groupingBy(p -> {
                int age = p.getAge() * new Random(10).nextInt();
                atomicInteger.set(age);
                return age;
            }, Collectors.groupingBy(p2 -> p2.getCityCode() + atomicInteger.get())));

如果您想了解更多关于AtomicInteger 的信息,请参阅atomic。基本上它是一个包装器,它将在线程之间保持其变量。

【讨论】:

  • 对不起,我没有解释我的问题。我已经更新了我的问题以解释我在第三个代码区域中的含义。
  • @PaulLemarchand,你为什么使用 AtomicInteger?你能详细说明一下吗?只是好奇:)
  • +1 @PaulLemarchand 将AtomicInteger (AI) 用作容器的方式是个好主意。也就是说,如果有人使用parallelStream 而不是stream,则此实现将不起作用。因为在这种情况下,多个线程可能会访问相同的AI(尽管一个接一个)。例如第一个线程将值 x 写入 AI 并假设在创建值端时,AI 将具有它写入的值。但是,当第二个线程将值 y 写入AI 时,此实现将陷入困境。但是话又说回来,OP似乎不需要parallelStream。所以+1。
  • 只是为了增加一个不同的视角,流是为了启用函数式编程。并且它违背了功能范式哲学来改变一些常见的变量。但现实世界的用例有时确实需要违背哲学。 medium.com/infocentric/…
  • Master Chief,Paul,你让我学到了很多关于lambda的知识,我必须花很多时间来消化知识,非常感谢。我认为Master way很棒,Paul way更适合这种情况。我成了你的粉丝。
【解决方案2】:

首先,您使用修改后的密钥收集所需的地图

Map<Integer, Map<Integer, List<Person>>> collect2 = personList.stream().collect(Collectors
        .groupingBy(p -> p.getAge() * new Random(10).nextInt(),
                Collectors.groupingBy(Person::getCityCode)));

然后改变地图。这种情况下的问题是您使用的是嵌套地图。并使用您想要change the key of inner Map 的外部地图的key。所以除了为每个外部 Key 创建一个新的内部 Map 之外别无他法。

在这里,我正在迭代外部映射的每个条目,并使用已经存在的内部映射创建一个新的正确(必需)内部映射。

collect2.entrySet().stream().forEach(e -> {
    Integer key = e.getKey();
    Map<Integer, List<Person>> oldValueMap = e.getValue();
    Map<Integer, List<Person>> newValueMap = new HashMap<>();
    oldValueMap.keySet().forEach(k -> {
        newValueMap.put(k + key, oldValueMap.get(k));
    });
    e.setValue(newValueMap);
});

【讨论】:

  • 哇,你让我大开眼界,它很专业,但有些难以阅读。这是工作。但我想问一个问题,如果这种方式比@Paul Lemarchand 的方式更循环?实际上,得到key1result并不是我的最终目的,我的疑惑是,如果第一组有一些参数,我想在第二组中使用它,是不是只有像Paul Lemarchand的方式? Paul Lemarchand 的方式简单易读,是不是安全性能好?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2017-11-02
  • 2021-06-18
  • 2017-04-21
  • 2017-05-01
  • 1970-01-01
相关资源
最近更新 更多