【问题标题】:Java8: Stream map two properties in the same streamJava8:流映射同一流中的两个属性
【发布时间】:2018-09-08 06:42:16
【问题描述】:

我有一个带有以下签名的课程Model

class Model {
        private String stringA;
        private String stringB;

        public Model(String stringA, String stringB) {
            this.stringA = stringA;
            this.stringB = stringB;
        }

        public String getStringA() {
            return stringA;
        }

        public String getStringB() {
            return stringB;
        }
}

我想将 List<Model> 映射到 List<String> 在单个流中同时包含 stringA 和 stringB

List<String> strings = models.stream()
                .mapFirst(Model::getStringA)
                .thenMap(Model::getStringB)
                .collect(Collectors.toList());

或:

List<String> strings = models.stream()
                .map(Mapping.and(Model::getStringA,Model::getStringB))
                .collect(Collectors.toList());

当然,它们都不能编译,但你明白了。

有没有可能?

编辑:

例子:

Model ab = new Model("A","B");
Model cd = new Model("C","D");
List<String> stringsFromModels = {"A","B","C","D"};

【问题讨论】:

  • 当您说“StringA 和 StringB”时,您的意思是串联吗?或者您的List&lt;String&gt; 是否应该在索引0 处包含StringA 用于您的Model,然后在索引0 处包含用于ModelStringB,然后在索引1 处包含[...] 和等等?
  • A Stream 通常不喜欢增加大小,这不是它通常的行为方式,您可以使用flatMap 实现您想要的,但这将是丑陋的。你有什么理由不想使用传统的for 循环?
  • @Mena 我的意思是第二种方式,所以List&lt;String&gt; strings 应该包含模型中的每个字符串,包括字符串 A 和字符串 B。我将提供一个例子。
  • @luk2302 这是实际的解决方案,但我想知道是否可以在流中解决它
  • 那么答案是“是的,但在性能方面既不会漂亮也不会更好”

标签: java java-8 java-stream


【解决方案1】:

flatMap是你的朋友:

models
    .stream()
    .flatMap(model -> Stream.of(model.getStringA(),model.getStringB()))
    .collect(Collectors.toList());

flatMap 接受一个类型 R 并期望返回一个新类型 RR 的流(来自列表、集合、数组)。对于每个 1 模型,您将获得 n 新元素(在本例中为 StringAStringB):

{model_1[String_A1,String_B1] , model_2[String_A2,String_B2] , model_3[String_A3,String_B3]}

你所有的n 元素 { [String_A1,String_B1], [String_A2,String_B2],[String_A3,String_B3]}

然后展平,将其放入具有结构的新流中

{String_A1,String_B1,String_A2,String_B2,String_A3,String_B3}

字符串类型。这就是您拥有新流的方式。

您可以使用flatMap,例如,当您有许多元素集合/流需要合并为一个时。更简单的解释,查看这个answer

【讨论】:

    【解决方案2】:

    您可以像这样依次列出所有值:

    List<String> resultSet =
                   modelList.stream()
                            .flatMap(e -> Stream.of(e.getStringA(), e.getStringB()))
                            .collect(Collectors.toList());
    

    传递给flatMap 的函数将应用于产生Stream&lt;String&gt; 的每个元素。这里需要使用flatMap 来将所有嵌套的Stream&lt;Stream&lt;String&gt;&gt; 折叠为Stream&lt;String&gt;,从而使我们能够将元素收集到List&lt;String&gt; 中。

    【讨论】:

    • @Sunflame 不客气。如果有助于澄清答案,我还添加了一些额外的解释:)。
    • 谢谢,现在如何使用flatMap 更清楚了,我认为它曾经将Collections 或Iterables 合并到一个流中。真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多