如何使用java流将嵌套for循环转换为Hashmap [英] How to convert nested for loop into Hashmap using java stream

查看:230
本文介绍了如何使用java流将嵌套for循环转换为Hashmap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用java流将下面嵌套的for循环转换为hashmap但是我在收集器步骤中受到了冲击。你可以帮忙吗?

I am trying to convert the below nested for loop into hashmap using java stream but i got struck in the collector step. Could you please help?

现有代码:

private static HashMap<String, Long> getOutput(List<Employee> eList) {
    HashMap<String, Long> outputList = new HashMap<>();
    for (Employee employee : eList) {
           List<Department> departmentList = employee.getDepartmentList();
              for (Department department : departmentList) {
                 if (department.getType().equals(DepartmentType.SCIENCE)) {
                     outputList.put(employee.getName(),department.getDepartmentId()));
                  }
              }
    }
    return outputList;
}

到目前为止我尝试过:

private static HashMap<String, Long> getOutput(List<Employee> eList) {
                       return  eList.stream()
                                    .flatMap(emp -> emp.getDepartmentList().stream()
                                    .filter(dept -> dept.getType().equals(DepartmentType.SCIENCE))
                                    .collect(HashMap::new, ???)
              }


推荐答案

看来你的主要问题是保留了流的当前 emp 之后的参考你已经完成了 flatMap 。为了保留这个参考,你需要 flatMap 到某种类可以持有员工和部门 - 例如通用的元组(又名配对)。

It seems like your main issue is preserving the stream's current emp reference after you've done the flatMap. To keep this reference, you will need to flatMap to some sort of class that can hold both the Employee and Department - such as a generic Tuple (aka Pair).

Java没有内置于其API中的直观Tuple类,因此您可以选择:

Java doesn't have an intuitive Tuple class built into it's API, so your options are:


  1. 使用第3页的第三方库提供一个元组类(例如 javatuples

  2. DIY:构建您自己的通用Tuple类(请参阅相关的 SO问题

  3. 快速:添加一个特定用途的私有内部类这个lambda

编辑:

评论(感谢@Holger!)已经明白,每个员工似乎有很多部门。我的原始代码冒着抛出异常的风险,因为会有重复的密钥,而OP的原始代码只会覆盖映射条目。考虑使用 groupingBy 收集器并更改此方法的返回类型。

The comments (thanks @Holger!) have enlightened that it appears that there are many departments per employee. My original code risks throwing an exception since there would be duplicate keys, while the OP's original code simply overwrites the map entries. Consider using the groupingBycollector and changing the return type of this method.

private static Map<String, List<Long>> getOutput(List<Employee> eList) {
  return eList.stream()
    // get a stream of employee / department pairs
    .flatMap(emp -> emp.getDepartmentList().stream().map(dep -> new EmployeeDepartmentPair(emp, dep))
    // filter the departments to SCIENCE
    .filter(x -> x.department.getType().equals(DepartmentType.SCIENCE))
    // group departmentIds by employee name
    .collect(Collectors.groupingBy(x -> x.employee.getName(), Collectors.mapping(x -> x.department.getDepartmentId(), Collectors.toList())))
}

原文(见上文编辑):

以下是使用选项3的一些更新代码:

Here's some updated code using option 3:

private static Map<String, Long> getOutput(List<Employee> eList) {
  return  eList.stream()
    .flatMap(emp -> emp.getDepartmentList().stream().map(dep -> new EmployeeDepartmentPair(emp, dep))
    .filter(x -> x.department.getType().equals(DepartmentType.SCIENCE))
    .collect(Collectors.toMap(x -> x.employee.getName(), x -> x.department.getDepartmentId()));
}

private static class EmployeeDepartmentPair {
  public final Employee employee;
  public final Department department;

  public EmployeeDepartmentPair(Employee emp, Department d) {
    this.employee = emp;
    this.department = d;
  }
}

这篇关于如何使用java流将嵌套for循环转换为Hashmap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆