Java syntax with MongoDB

2019-01-23 05:35发布

问题:

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);
}

回答1:

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.



回答2:

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);
}


标签: java mongodb