【问题标题】:convert 2 streams in one stream and map()将 2 个流转换为一个流和 map()
【发布时间】:2021-03-01 10:30:41
【问题描述】:

我有一个 StudentLogin 数组,其中名称是键,值是值

"studentLogin" : [ 
        {
            "name" : "firstName_key",
            "value" : "<actual first Name value>"
        },
        {
            "name" : "lastName_key",
            "value" : "<actual last Name value>"
        },
        ....
      ]

我有一个方法,我将 studentLogin 列表作为输入参数,我需要检查 firstName(key) 和 lastName(key) 是否存在于同一个索引中,如果是,那么我需要连接实际值来自同一索引的名字和姓氏。

我写了下面的方法,但是使用了两个流,我想把它转换成一个流。

  public String convertStudentLoginToFullName(List<StudentLogin> studentLogin) {
      if (null != studentLogin) {
        String firstName = studentLogin.stream()
                .filter(x -> "firstName_key".equalsIgnoreCase(x.getName()))
               .map(x->x.getValue())
                .findFirst()
                .orElse(null);
        String lastName = studentLogin.stream()
                .filter(x -> "lastName_key".equalsIgnoreCase(x.getName()))
                .map(x -> x.getValue())
                .findFirst()
                .orElse(null);
        String fullName=firstName+" "+lastName;
        return fullName;
      }
    }
    return null;
  }

【问题讨论】:

  • 如果我理解正确,你想要&lt;actual first Name value&gt; &lt;actual last Name value&gt;
  • 是的,没错。
  • 为什么studentLogin 甚至是一个列表?你不觉得,一个对象可以更好地代表信息吗?
  • 是的好问题,以这种方式思考,假设学生登录到大学中的不同应用程序,因此在这种情况下,studentLogin 可能对所有这些应用程序都有不同的 id/pwd,因此创建了一个列表,有意义吗?

标签: java list collections java-8 java-stream


【解决方案1】:

在这种情况下,您可以使用方法Collectors.toMap​(keyMapper,valueMapper),如下所示:

public static void main(String[] args) {
    List<StudentLogin> studentLoginList = List.of(
            new StudentLogin(null, null),
            new StudentLogin("firstName_key", "<actual first Name value>"),
            new StudentLogin("lastName_key", "<actual last Name value>"));

    Map<String, String> studentLoginMap = studentLoginList.stream()
            // check if name and value are not null
            .filter(stlog -> stlog.getName() != null
                    && stlog.getValue() != null)
            // collect to map
            .collect(Collectors.toMap(
                    StudentLogin::getName,
                    StudentLogin::getValue));

    String firstName = studentLoginMap.get("firstName_key");
    String lastName = studentLoginMap.get("lastName_key");

    if (firstName != null && lastName != null) {
        System.out.println(firstName + " " + lastName);
        // <actual first Name value> <actual last Name value>
    }
}
public static class StudentLogin {
    String name;
    String value;

    public StudentLogin(String name, String value) {
        this.name = name;
        this.value = value;
    }

    public String getName() { return name; }
    public String getValue() { return value; }
}

另见:Invert a Map with redundant values to produce a multimap

【讨论】:

    【解决方案2】:

    一种方法是先将StudentLogin 列表转换为Map

    Map<String, String> studentLoginMap = studentLogin.stream()
        .collect(Collectors.toMap(
            StudentLogin::getName(),
            StudentLogin::getValue(),
            (old, new) -> old
        ))
    

    注意如果有多个StudentLogins同名,我使用合并函数(old, new) -&gt; old来解决冲突。始终使用与您在原始代码中所做的匹配的旧值 - 取第一个匹配 firstName_keylastName_key 的值。

    现在,您可以访问 studentLoginMap 的值并在名字和姓氏都存在的情况下进行连接:

    String firstName = studentLoginMap.get("firstName_key");
    String lastName = studentLoginMap.get("lastName_key");
    if (firstName != null && lastName != null) {
       String result = firstName + " " + lastName;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-15
      • 2019-12-06
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多