【问题标题】:Use Java 8 stream to create and a Collection<Stream>使用 Java 8 流创建和 Collection<Stream>
【发布时间】:2017-05-09 16:49:27
【问题描述】:

我有课

class ColumnTags {
    String Name;
    Collection<String> columnSemanticTags;

    // constructor and getter and setters and other relevant attributes
}

我想从给定名称的 ColumnTag 列表中获取 columnSemanticTags。

对应的方法如下

public Collection<String> getTags(String colName, List<ColumnTags> colList) 
{
   Collection<String> tags = new ArrayList();
   for(ColumnTag col:colList){
        if(colName.equals(col.getName())){
              tags = col.getColumnSemanticTags();
              break;
              }
     }
    return tags;
 }

想要将 for 循环转换为 java 流。我试过了

   tags = colList.stream().filter(col -> colName.equals(col.getName()))
                   .map(col -> col.getColumnSemanticTags())
                   .collect(Collectors.toCollection());

我收到编译错误。我不知道应该是什么 Supplier 。尝试过 ArrayList::new 。我也尝试将其转换为 ArrayList ,但没有成功。 有人可以告诉我我假设什么是错误的,或者处理这种情况的预期方法是什么。 通过该解决方案,有人可以解释为什么 .collect() 是解决此解决方案的错误方法。

【问题讨论】:

  • 如果没有找到匹配项,是否有任何理由返回新的ArrayList,而不是直接返回Collections.emptyList()

标签: java java-8 java-stream


【解决方案1】:
public Collection<String> getTags(String colName, List<ColumnTags> colList) {
    return colList.stream().filter(col -> colName.equals(col.getName()))
        .map(col -> col.getColumnSemanticTags())
        .findFirst().orElse(new ArrayList<>());
}

【讨论】:

    【解决方案2】:

    如果你真的想使用collect,你必须调用flatMap。这会将所有列表(来自map(col -&gt; col.getColumnSemanticTags()))合并到一个包含所有项目的流中。

     List<String> tags = colList.stream()
                    .filter(col -> colName.equals(col.getName()))
                    .map(col -> col.getColumnSemanticTags())
                    .flatMap(collection -> collection.stream())
                    .collect(Collectors.toList());
    

    【讨论】:

    • OP 在找到第一个元素后跳出 for 循环。
    • 没错,这只是使用 collect() 的一种解决方法。
    【解决方案3】:

    解决此问题的更简单方法是简单地过滤 Stream 以准确找到您要查找的内容。如果找到,则返回,否则返回空ArrayList

    return colList.stream()
                  .filter(c -> colName.equals(c.getName()))
                  .map(ColumnTag::getColumnSemanticTags)
                  .findFirst()
                  .orElseGet(ArrayList::new);
    

    【讨论】:

    • 你能解释一下为什么我的尝试是错误的吗?为什么使用 .collect() 以错误的方式解决此解决方案。
    • 当你使用Collectors#toCollection时,它会将Stream收集到一个Collection&lt;Collection&lt;String&gt;&gt;中,而你只需要一个Collection&lt;String&gt;
    • 如果我没有休息;那么我应该使用什么 - flatMap() 后跟一个收集。
    • 删除break 相当于在Stream 中找到共享colName 的最后一个元素,这在使用Stream 时很难实现。如果您没有使用Stream,您可以简单地向后迭代Collection,并在找到第一个元素后中断。
    • 获得最后一场比赛并不难。只需将.findFirst().orElseGet(ArrayList::new); 替换为.reduce( (a,b) -&gt; b ) .orElseGet(ArrayList::new);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 2021-10-07
    相关资源
    最近更新 更多