首页 > 解决方案 > Lambda expression used to replace the nested for-loop, for some reason, does not work

问题描述

I have the following situation, where the lambda expression i used to replace a working for loop does not work. Have no clue as to why this fails

public class Abc implements IAbc {

    // some fields
    ...
    // field i'm interested in
    @Inject @Any
    private Instance<HandlerInterface> handlers;

    // more members
    ...
    // method i'm interested in
    @Override
    public boolean hasHandler(List<Order> orders) {
        for (Order anOrder : orders) {
            for (HandlerInterface aHandler : handlers) {
                // following canHandler() is implemented by each 
                // handler that implements the HandlerInterface
                if(aHandler.canHandle(anOrder)) {
                    return true;
                }
            }
        return false;
    }
    // rest of the class content
    .....
}

So I was actually trying to replace the above code, within the method, with Lambdas (to which i'm new). The following was my replacement code

public boolean hasHandler(List<Order> orders) {
    return orders.stream().anyMatch(order ->
        Stream.of(handlers).map(Provider::get).anyMatch(handler ->
            handler.canHandle(order)));
}

The above lambda expression fails at handler.canHandle with AmbiguousResolutionException. I can't find out why it works with the for loop and not with stream. Im sure im doing something wrong here - but have no clue as to what. Any help on this is greatly appreciated.

标签: javalambdajava-8java-stream

解决方案


我假设Instance<HandlerInterface>实现Iterable<HandlerInterface>(或者您将无法在增强的 for 循环中使用它)。

这意味着您可以通过调用创建Streamthis 的元素IterableStreamSupport.stream(handlers.spliterator(), false);

所以现在,您的方法可以转换为使用 Streams,如下所示:

public boolean hasHandler(List<Order> orders) {
    return orders.stream()
                 .anyMatch(o -> StreamSupport.stream(handlers.spliterator(), false)
                                             .anyMatch(h -> h.canHandle(o)));
}

注意:我删除了该.map(Provider::get)步骤,因为它在您的原始嵌套循环代码中没有相应的步骤。


推荐阅读