Подтвердить что ты не робот

Синтаксис Java с помощью MongoDB

Я вхожу в введение в MongoDB для java. Там есть пример кода для извлечения всех документов в коллекции. Код работает, но я нахожу его немного... неуклюжим из-за отсутствия лучшего слова. Мне интересно, есть ли какая-то конкретная причина, которая делает это необходимым. Данный пример:

FindIterable<Document> iterable = db.getCollection("restaurants").find();
iterable.forEach(new Block<Document>() {
    @Override
    public void apply(final Document document) {
        System.out.println(document);
    }
});

Есть ли причина, по которой экземпляр Block должен быть создан на каждой итерации forEach в приведенном выше примере? Почему бы не что-то более прямолинейное:

FindIterable<Document> iterable = db.getCollection("restaurants").find();
for (Document document : iterable) {
    System.out.println(document);
}
4b9b3361

Ответ 1

Хотя вы можете, конечно, использовать форму, которую вы предложили:

for (Document document : col.find()) {
    // do something
}

он вводит проблему, когда тело цикла for генерирует исключение: если это произойдет, курсор не будет закрыт. Правильная идиома для защиты от этого заключается в том, чтобы явно использовать MongoCursor (который реализует Closeable):

try (MongoCursor<Document> cursor = col.find().iterator()) {
    while (cursor.hasNext()) {
        System.out.println(cursor.next());
    }
}

Метод forEach - это всего лишь немного синтаксического сахара, чтобы избежать необходимости в коде приложения, чтобы беспокоиться о необходимости вручную закрыть курсор.

Если вы не хотите создавать новый блок для каждой итерации, вы можете реорганизовать свой код, вытащив анонимное создание внутреннего класса, например:

Block<Document> block = new Block<Document>() {
    @Override
    public void apply(final Document document) {
        System.out.println(document);
    }
};
col.find().forEach(block);

Конечно, это даже clunkier, поэтому, если вы можете использовать Java 8, вы можете заменить все это на лямбда:

col.find().forEach((Block<Document>) document -> {
    System.out.println(document);
});

или в этом случае просто:

col.find().forEach((Block<Document>) System.out::println);

lambda metafactory гарантирует, что не создаются ненужные объекты.

Ответ 2

Я задал себе тот же вопрос, и я нашел довольно простым следующий код для обработки этой ситуации:

List<Document> restaurants = db.getCollection("restaurants").find().into(new ArrayList<Document>());

for (Document restaurant : restaurants) {
    System.out.println(restaurant);
}