【问题标题】:Java generics incompatible types (no instance(s) of type variable(s) exist)Java 泛型不兼容类型(不存在类型变量的实例)
【发布时间】:2019-11-08 05:59:24
【问题描述】:

问题标题可能与其他帖子相同,但内容不同。所以请不要将其标记为重复。

问题

我有以下课程:

public class SCDTO extends RDTO {
    private List<String> sCPairs = Collections.emptyList();

    public SCDTO(List<String> sCPairs) {
        this.sCPairs = sCPairs;
    }

    //Getter setter
    
}

我正在尝试使用下面的 lambda 表达式来设置 sCPairs

sCPairsObject.setSCPairs(
         util.getSCMap().entrySet().stream()
        .filter(entry -> entry.getValue().contains("abc"))
        .collect(Collectors.toCollection(ArrayList<String>::new))
);

但我有一个编译错误说:

no instance(s) of type variable(s) exist so that Entry<String, List<String>> conforms to String

util.getSCMap 返回Map&lt;String, List&lt;String&gt;&gt;

谁能解释一下为什么会发生这种情况以及如何解决?

谢谢。

【问题讨论】:

  • entrySet() 将返回一个 Set&lt;Entry&lt;K,V&gt;&gt; 所以如果你想将它们收集到一个 List&lt;String&gt; 你将需要一个 map(...) 在两者之间 - 或者如果 V 实际上是一个 @987654332 @你甚至可能需要flatMap(...)

标签: java generics lambda java-8


【解决方案1】:

由于您要将Map&lt;String, List&lt;String&gt;&gt; 转换为List&lt;String&gt;,其中列表应该是所有匹配值列表的并集,您需要flatMap() 将这些值列表上的流连接成单个流。

此外,您似乎不需要键,因此只需在地图的值上流式传输:

List<String> scPairs = util.getSCMap().values().stream() //stream on the values only
                           .filter( l -> l.contains( "abc" ) ) //filter the lists
                           .flatMap( Collection::stream ) //join the individual streams
                           .collect( Collectors.toList() ); //collect the result into a single list

【讨论】:

    【解决方案2】:

    您不需要遍历entrySet,因为您根本没有使用密钥。您可以获取Map 的值并对其进行过滤。看起来像这样

    sCPairsObject.setSCPairs(util.getSCMap()
       .values()
       .stream()
       .filter(entry -> entry.contains("abc"))
       .flatMap(List::stream)
       .collect(Collectors.toList());
    

    【讨论】:

    • 您可以将变量 'entry' 重命名为例如'value' 避免混淆
    【解决方案3】:

    您正在从地图流式传输条目:

    sCPairsObject.setSCPairs(util.getSCMap().entrySet().stream()
    

    然后过滤掉其中的一些:

    .filter(entry -> entry.getValue().contains("abc"))
    

    现在您需要将条目映射到 List,例如:

    .map(entry -> entry.getValue())
    

    并将所有这些列表的内容作为一个流进行流式传输:

    .flatMap(List::stream)
    

    最后将值收集到一个列表中:

    .collect(Collectors.toList());
    

    【讨论】:

    • 非常感谢。我无法将所有回复都标记为答案,否则我也将其标记为答案。
    • 我想我是第一个给出完整解决方案的答案。但是 IMO Murat 的答案是目前最好的,因为它考虑到您没有使用密钥,因此您不需要遍历条目。当前接受的答案实际上并不能解决您的问题,因为它没有映射值。
    • 你能解释一下做 .flatMap(List::stream) 的需要吗?如果我不这样做会发生什么? @Adriaan Koster
    • flatmap 允许您将列表流的内容收集到单个流中。如果您不使用它,则流将包含多个列表。然后如果你确实 collect(Collectors.toList()) 你最终会得到一个 List> 而不是 List
    【解决方案4】:

    您的流管道会找到值 List&lt;String&gt; 包含 String "abc" 的所有 Map 条目,并尝试将它们收集到 List&lt;String&gt; 中。

    您没有指定如何将每个通过过滤器的Map.Entry&lt;String,List&lt;String&gt;&gt; 元素转换为String。根据所需的逻辑,您可能在过滤器之后缺少map() 步骤。

    例如,如果您希望收集具有通过过滤器的值的所有键到List&lt;String&gt;

     sCPairsObject.setSCPairs(util.getSCMap()
                                  .entrySet()
                                  .stream()
                                  .filter(entry -> entry.getValue().contains("abc"))
                                  .map(Map.Entry::getKey)
                                  .collect(Collectors.toCollection(ArrayList<String>::new)));
    

    【讨论】:

    • 非常感谢。现在我明白了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-11
    • 1970-01-01
    • 2018-08-16
    相关资源
    最近更新 更多