Java8 - How does explicit type matches one variant - not other type?


I have a simple snippet as below. I referred this

List<Document> list = new LinkedList<Document>(); FindIterable<Document> itr = collection.find(findQuery) .forEach((Document doc) -> list.add(doc)); return list;

It compiles without any issues.

<ol><li>I guess that we are telling compiler that doc is of type Document. Why is it needed?</li> </ol>

But If I do the below, it throws ambiguous error. I referred this But couldn't relate and understand exactly.

collection.find(findQuery).forEach(list::add); <ol start="2"><li>

Could anyone please explain why second statement is not working?

</li> <li>

is there any better way of writing the first one [working one]?

</li> </ol>

Java version: 1.8.0_231

import statements:

import java.util.List; import java.util.Optional; import com.mongodb.client.FindIterable; import org.bson.Document;

FindIterable inherits two forEach methods:


com.mongodb.client.MongoIterable.forEach(Block<? super TResult>)

</li> <li>

java.lang.Iterable.forEach(Consumer<? super T>)

</li> </ul>

You could rewrite your paramter with either

Consumer<Document> consumer = documents::add; Block<Document> block = list::add;

And either will work. These too will work:

.forEach((Consumer<Document>) doc -> list.add(doc)) .forEach((Consumer<Document>) list::add);

However, when you call forEach(list::add) or forEach(doc -> list.add(doc)), the compiler is unable to pick which overload will determine the method reference's target type (because the expression is compatible with both in that context).

Now, I'm not 100% sure why .forEach((Document doc) -> list.add(doc)) successfully selects/links the signature of Consumer<Document> instead of the one with Block<? super Document>, I'm surmizing it has to do with the generic bounds (but I'm still reading on this).

The choice for you should be easy because the Block<? super Document> version is deprecated.


The problem is that forEach is just a Consumer, which has a single method void accept(T element), and you're trying to return a value.

The "ambiguous" error in the first version was subject to other posts here.

You can do (I'd consider that more idiomatic)

return StreamSupport.stream(collection.find(findQuery).spliterator(), false) .collect(Collectors.toList());

As it is explicited in the lamba target typing


the Java compiler uses the target type of the context or situation in which the lambda expression was found. It follows that you can only use lambda expressions in situations in which the Java compiler can determine a target type


In your second snippet, the compiler cannot determine the target type of the lambda. Why?

Because when you use Method Reference the JRE infers the method type arguments, which in this case are ambiguous (e.g method reference works well only if there is non-ambiguous inference)

The JRE don't know if your using :

com.mongodb.client.MongoIterable.forEach(Block<? super TResult>)


java.lang.Iterable.forEach(Consumer<? super T>)

That's why your first snippet works. By casting your Object. You get rid of this ambiguity.



  • Linking to a static lib compiled with MSVC
  • General Python socket questions with several answers
  • How To call Lua function from Javascript
  • how to inject a file into http request
  • Version in jar name
  • How to store confidential PDF documents (file system vs. SQL) if we only use forms authentication
  • How to change the default browser in visual studio code latest released?
  • Select running balance from table credit debit columns
  • python: Using ncurses when underlying library logs to stdout
  • Rebuilding again and again to view the imported QML file changes
  • Rails Template Error with Heroku
  • Set selected using jQuery
  • Get an image from the video
  • Creating and managing two independent random number sequences
  • How to make responsive images in flutter?
  • Bazel failed to include a external static library .a
  • Get last 15 lines from a large file in SFTP with phpseclib [duplicate]
  • ROR + MVC Disable Browser Cache
  • watir webdriver - window not found
  • read.table returning character matrix, would like numeric
  • Dynamically run java code with Process
  • Do iTunesConnect external testers get updates for *every* uploaded ipa file after Beta Approval?
  • How to run Daphne Server (Django Channels) & workers in the background?
  • Could not resolve all files for configuration ':react-native-vector-icons:classpath'
  • Draw 9 patch dotted /dashed line on Android
  • Implementation of timeout in LDAP
  • Symfony - Setting Cookie onKernelRequest
  • Why do you need 2 Javascript files for cross-platform Cordova plugin?
  • Create an Office365 mailbox from within C# Web API method
  • select an input by value?
  • PHPMailer return to AJAX
  • I am consuming a WCF service that requires headers from a .NET 2 website. How can I programmatically
  • `$http:badreq Bad Request Configuration` - from angular post method, what is wrong here?
  • How to encrypt Connectionstring written in web.config from codebehind?
  • Can someone explain this Java code (formatting the output using System.out.format) to me?
  • Call Microservice from another Microservice within Docker
  • How to use FirstOrDefault inside Include
  • What does the “id” field in an Android “Google Play Music” broadcast intent correspond to?
  • Time Complexity of Fibonacci Algorithm [duplicate]
  • XSLT Transformation to validate rules in XML document