【问题标题】:Stream and Filter operations on a Map地图上的流和过滤操作
【发布时间】:2017-12-06 05:43:36
【问题描述】:

我有一个 EdmPortfolio 类型,它有 id (int)、name (String) 和标签,它是一个地图作为它的成员。

EdmPortfolio 的 id 为 1,名称为 Portfolio1 和 Map 可以具有以下值, 分析师,约翰 美国地区

我有一个列表,最后我想要一个地图,其中包含来自所有投资组合的所有地图值。另一个 EdmPortfolio 的 id 可能为 2,名称为 Portfolio2 和 Map with values Analyst, Smith 地区,英国

我想要一个包含值的组合地图 地区“美国”、“英国” 分析师“约翰”、“史密斯”

分析员和地区是地图的关键。 它结合了两个地图。我有以下代码,但我有点迷茫

List<Map<Tag,String>> portfolioTagsList = new ArrayList<>();
            for (EdmPortfolio edmPortfolio : edmPortfolioList) {
              Map<Tag,String> portfolioTags =  edmPortfolio.getPortfolioTags().entrySet()
                        .stream()

                        .filter(e -> (e.getValue() != ""|| e.getValue() !=null))
                        .collect(Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue
                        ));


                portfolioTagsList.add(portfolioTags);
            }
            Map<Tag,String> finalTags = portfolioTagsList.stream()
                    .flatMap(m -> m.entrySet().stream())
                    .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.joining(",",Map.Entry::getValue)));

我得到的非静态方法不能从静态上下文中引用。我如何做到这一点?

感谢您的宝贵时间

【问题讨论】:

标签: filter java-8 java-stream


【解决方案1】:

我会这样做:

Map<Tag,String> finalTags = edmPortfolioList.stream()
.flatMap(edmPortfolio -> edmPortfolio.getPortfolioTags().entrySet().stream())
.filter(e -> (e.getValue() != "" || e.getValue() !=null)) // this seems weird, but just keeping
.collect(Collectors.groupingBy(e -> e.getKey(), 
    Collectors.mapping(ev -> ev.getValue(), 
        Collectors.joining(",")));

顺便说一句:有什么理由把它分成两个流?

【讨论】:

  • @Holger 由于 OP 没有提供确切的错误消息或错误发生的位置,我只是尝试提出一个简化版本,推断类型较少,因此可以成功实现相同的结果。顺便说一句,您对加入的评论是有道理的,我相应地编辑了我的答案。
  • OP 确实提供了确切的错误消息,虽然不是它发生的位置,但是对于“无法从静态上下文引用非静态方法”,位置不会是无论如何都有帮助。我经常看到它,并且总是对导致它的实际问题感到困惑。将其简化为单个操作确实是一件好事,您已经获得了我的支持,但是对于编译器,它增加了更多的推理工作,使得跟踪这个可怕的“非静态方法不能从静态上下文引用”错误。我真的希望未来在这方面的编译器改进......
  • 是的,这是有道理的,位置与此错误无关。我现在只是想知道 Eclipse Java 编译器是否有不同的功能,因为我似乎从未在此消息下报告此类失败。
  • 是的,ECJ 的工作方式不同。我也看到了 ECJ 的误导性错误消息,但不是这样偏好单个错误。此外,它们用于不同的上下文,例如IDE 的助手有所作为,例如Eclipse 更渴望(比 Netbeans)插入所需的 import 语句,这使得遇到实际上是缺少导入的 lambda 相关错误的可能性较小。
  • 谢谢。我试图理解和简化这就是为什么我把它分成两个流..没有理由
【解决方案2】:

不幸的是,“nonstatic method cannot be referenced from static context”是 javac 在类型推断失败时经常出现的错误,尤其是在方法引用或 lambda 表达式的上下文中。实际原因可能是错误的泛型类型参数、忘记​​的 import 语句、在不适当的地方使用了 lambda 表达式或方法引用,甚至是某处放错位置或忘记了大括号。

在您的情况下,它是 Collectors.joining(",",Map.Entry::getValue),因为该收集器没有可以接受方法引用的函数类型的参数。
你应该改用Collectors.mapping(Map.Entry::getValue, Collectors.joining(","))

除此之外,跟随BrunoJCM’s suggestion使用单流操作,注意过滤条件。 e.getValue() != "" || e.getValue() !=null 没有任何意义,因为引用永远不能同时是对 "" 的引用和 null 引用,因此,这个条件总是满足的。您很可能想要表示该字符串不能是 null 并且 不能是空字符串。在这方面,您不应通过引用比较字符串,而应使用equals。对于空字符串的测试,可以使用isEmpty() 代替equals("")。所以条件应该是e.getValue()!=null &amp;&amp; !e.getValue().isEmpty()。注意顺序,因为我们只有在验证它不是null 之后才能调用isEmpty()

【讨论】:

  • 非常感谢您的解释。我也修改了条件。更改映射工作
猜你喜欢
  • 2020-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多