Простой способ конвертировать Iterable в коллекцию - PullRequest
378 голосов
/ 20 июня 2011

В моем приложении я использую стороннюю библиотеку (точнее Spring Data для MongoDB).

Методы этой библиотеки возвращают Iterable<T>, тогда как остальная часть моего кода ожидает Collection<T>.

Есть ли где-нибудь полезный метод, который позволит мне быстро конвертировать один в другой? Я бы не хотел создавать в своем коде кучу циклов foreach для такой простой вещи.

Ответы [ 16 ]

5 голосов
/ 15 октября 2015

Так как RxJava - это молот, и это похоже на гвоздь, вы можете сделать

Observable.from(iterable).toList().toBlocking().single();
5 голосов
/ 24 апреля 2014

В Java 8 вы можете сделать это, чтобы добавить все элементы от Iterable до Collection и вернуть его:

public static <T> Collection<T> iterableToCollection(Iterable<T> iterable) {
  Collection<T> collection = new ArrayList<>();
  iterable.forEach(collection::add);
  return collection;
}

Вдохновленный ответом @Afreys.

5 голосов
/ 21 июня 2011

Как только вы позвоните contains, containsAll, equals, hashCode, remove, retainAll, size или toArray, вам все равно придется пройти через элементы.

Если вы иногда вызываете только такие методы, как isEmpty или clear, я полагаю, вам было бы лучше, если бы коллекция создавалась лениво.Например, вы можете иметь поддержку ArrayList для хранения ранее повторенных элементов.

Я не знаю ни одного такого класса в какой-либо библиотеке, но это должно быть довольно простое упражнение для записи.

3 голосов
/ 08 августа 2016

Вот SSCCE для отличного способа сделать это в Java 8

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class IterableToCollection {
    public interface CollectionFactory <T, U extends Collection<T>> {
        U createCollection();
    }

    public static <T, U extends Collection<T>> U collect(Iterable<T> iterable, CollectionFactory<T, U> factory) {
        U collection = factory.createCollection();
        iterable.forEach(collection::add);
        return collection;
    }

    public static void main(String[] args) {
        Iterable<Integer> iterable = IntStream.range(0, 5).boxed().collect(Collectors.toList());
        ArrayList<Integer> arrayList = collect(iterable, ArrayList::new);
        HashSet<Integer> hashSet = collect(iterable, HashSet::new);
        LinkedList<Integer> linkedList = collect(iterable, LinkedList::new);
    }
}
2 голосов
/ 20 февраля 2013

Два замечания

  1. Нет необходимости конвертировать Iterable в Collection для использования foreach. loop - Iterable может быть использован в таком цикле напрямую, нет синтаксическая разница, поэтому я с трудом понимаю, почему вообще был задан исходный вопрос.
  2. Предложенный способ преобразования Iterable в Collection небезопасен (то же самое относится и к CollectionUtils) - нет гарантии, что последующие вызовы метода next () вернут разные экземпляры объекта. Более того, это беспокойство не чисто теоретическое. Например. Итеративная реализация, используемая для передачи значений в метод Reduce Hadoop Reducer, всегда возвращает один и тот же экземпляр значения, только с разными значениями поля. Поэтому, если вы примените makeCollection сверху (или CollectionUtils.addAll (Iterator)), вы получите коллекцию со всеми идентичными элементами.
1 голос
/ 20 июня 2017

Попробуйте StickyList из Cactoos :

List<String> list = new StickyList<>(iterable);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...