I'm going through the intro to MongoDB for java. There's some example code to retrieve all the documents in a collection. The code works, but I find it a bit...clunky for lack of a better word. I'm wondering if there's a specific reason that makes it necessary. The given example is:
FindIterable<Document> iterable = db.getCollection("restaurants").find();
iterable.forEach(new Block<Document>() {
@Override
public void apply(final Document document) {
System.out.println(document);
}
});
Is there some reason a Block
instance has to be created in every iteration of the forEach
in the above example? Why not something a little more straightforward like:
FindIterable<Document> iterable = db.getCollection("restaurants").find();
for (Document document : iterable) {
System.out.println(document);
}
While you can certainly use the form that you suggested:
for (Document document : col.find()) {
// do something
}
it introduces a problem when the body of the for loop throws an exception: if this happens the cursor will not be closed. The proper idiom to guard against that is to use MongoCursor (which implements Closeable) explicitly:
try (MongoCursor<Document> cursor = col.find().iterator()) {
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
The forEach method is just a bit of syntactic sugar to avoid the need for application code to worry about having to close the cursor manually like this.
If you don't want to create a new Block for each iteration, you can refactor your code pull out the anonymous inner class creation, e.g.:
Block<Document> block = new Block<Document>() {
@Override
public void apply(final Document document) {
System.out.println(document);
}
};
col.find().forEach(block);
Of course that's even clunkier, so if you are able to use Java 8, you can replace the whole thing with a lambda:
col.find().forEach((Block<Document>) document -> {
System.out.println(document);
});
or in this case simply:
col.find().forEach((Block<Document>) System.out::println);
The lambda metafactory will ensure that no unnecessary objects are created.
I asked myself the same question and I found pretty easy the following code to handle that situation:
List<Document> restaurants = db.getCollection("restaurants").find().into(new ArrayList<Document>());
for (Document restaurant : restaurants) {
System.out.println(restaurant);
}