【问题标题】:Java 8 - Lambda Expression Convert List<String> to List<DTO>Java 8 - Lambda 表达式将 List<String> 转换为 List<DTO>
【发布时间】:2020-03-08 21:29:47
【问题描述】:

我有一个这样的列表。想要对StringList 进行一些过滤和转换为ListDTO

    public static void main(String[] args) {

        String[] te = {"a","B_1","c","d","e"};      
        String[] con = {"a","b","ca"};

        List<String> S  = Arrays.asList(te).parallelStream()
                .map(x -> x.replace(ISConstants.domainName, ""))
                .filter(x -> (!x.contains("_"))? ArrayUtils.contains(con, x.toLowerCase()): ArrayUtils.contains(con, x.split("_")[0].toLowerCase()))
                .filter(x -> !x.equalsIgnoreCase("b"))
                .collect(Collectors.toList());

//          List<UserDTO> ls = l.forEach;
//          System.out.println(l);

    }

在这里你可以看到,我有一个列表 S 现在我想将该列表 S 转换为 UserDTO 列表,其中我有一个方法 setUserName 并希望将字符串从 S 设置为 userName 到 ls。

任何人都知道我如何使用现有的 lambda 表达式或新的表达式来执行此操作。

【问题讨论】:

  • 如果需要更多说明,请告诉我。

标签: java arrays regex java-8 java-stream


【解决方案1】:

通过使用另一个map 操作,例如:

List<UserDTO> users  = Arrays.asList(te).parallelStream()
        .map(x -> x.replace(ISConstants.domainName, ""))
        .filter(x -> (!x.contains("_"))? ArrayUtils.contains(con, x.toLowerCase()): ArrayUtils.contains(con, x.split("_")[0].toLowerCase()))
        .filter(x -> !x.equalsIgnoreCase("b"))
        .map(s -> new UserDTO(s)) // or 'UserDTO::new' by using a constructor with 'name' being set
        .collect(Collectors.toList());

(基于Holger's comment)并使用正则表达式进一步改进它,例如:

List<UserDTO> users = Arrays.asList(te).parallelStream()
        .map(x -> x.replace(ISConstants.domainName, ""))
        .filter(x -> !x.equalsIgnoreCase("b")) // filter in using simpler condition first
        .filter(x -> ArrayUtils.contains(con, x.replaceFirst("_.*", "").toLowerCase())) // simplified using regex
        .map(s -> new UserDTO(s)) // or 'UserDTO::new' by using a constructor with 'name' being set
        .collect(Collectors.toList());

【讨论】:

  • 这里可以使用方法引用.map(UserDTO::new)来代替lambda。
  • @MushifAliNawaz 是的,在构造函数中成立。答案的目的是强调方法。
  • 不过,可能值得一提的是,.filter(x -&gt; (!x.contains("_"))? ArrayUtils.contains(con, x.toLowerCase()): ArrayUtils.contains(con, x.split("_")[0].toLowerCase())) 可以替换为更简单的.filter(x -&gt; ArrayUtils.contains(con, x.replaceFirst("_.*", "").toLowerCase())),并且在另一个过滤器之前执行.filter(x -&gt; !x.equalsIgnoreCase("b")) 是有益的,因为它更易于测试和减少所需数量的复杂测试。
  • 让我们假设 .map(s -> new UserDTO(s)) 而不是这个 如果我使用 .map(x -> { UserDTO u = new UserDTO(); u.setUserName(x) ; return u; }) 那么会对性能有影响
  • @Mak 如果你比较两者,你最终要做的就是创建一个UserDTO 的新实例,所以你不会发现那里有任何性能影响。
【解决方案2】:

正如其他答案所示,您可以使用接收 String 并将用户名设置为 DTO 的构造函数。

或者,如果你不能添加这样的构造函数,你可以这样做:

List<UserDTO> result = Arrays.asList(te).stream()
        .map(x -> x.replace(ISConstants.domainName, ""))
        .filter(x -> !x.contains("_") ? 
                     ArrayUtils.contains(con, x.toLowerCase()) : 
                     ArrayUtils.contains(con, x.split("_")[0].toLowerCase()))
        .filter(x -> !x.equalsIgnoreCase("b"))
        .map(x -> {
                     UserDTO u = new UserDTO();
                     u.setUserName(x);
                     return u;
         })
        .collect(Collectors.toList());

这里我使用Stream.map 将字符串转换为UserDTO,并将该字符串设置为用户名。

【讨论】:

  • 是的,我一直在寻找这个,但是这里的性能呢?专门针对这部分 .map(x -> { UserDTO u = new UserDTO(); u.setUserName(x); return u; }
  • 嗨@Mak,没有性能损失,我们正在为每个字符串创建一个 DTO
  • 也许你可以提取一段代码,使用构造函数在 UserDTO 中设置用户名,然后你更改为 ``` .map(UserDTO::new)``` 以获得更好的可读性并为您提供微小的性能改进。
【解决方案3】:

假设DTO有一个构造函数,它需要一个String,你可以映射它:

List<DTO> S  = Arrays.asList(te).parallelStream()
            .map(x -> x.replace(ISConstants.domainName, ""))
            .filter(x -> (!x.contains("_"))? ArrayUtils.contains(con, x.toLowerCase()): ArrayUtils.contains(con, x.split("_")[0].toLowerCase()))
            .filter(x -> !x.equalsIgnoreCase("b"))
            .map(x -> new DTO(x))
            .collect(Collectors.toList());

或使用方法参考更容易:

List<DTO> S  = Arrays.asList(te).parallelStream()
            .map(x -> x.replace(ISConstants.domainName, ""))
            .filter(x -> (!x.contains("_"))? ArrayUtils.contains(con, x.toLowerCase()): ArrayUtils.contains(con, x.split("_")[0].toLowerCase()))
            .filter(x -> !x.equalsIgnoreCase("b"))
            .map(DTO::new)
            .collect(Collectors.toList());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 2019-07-31
    • 2015-03-20
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多