Łatwy sposób na konwersję Iterable do kolekcji
W mojej aplikacji używam 3rd party library(Spring Data for MongoDB by być dokładnym).
Metody tej biblioteki zwracają Iterable<T>
, podczas gdy reszta mojego kodu oczekuje Collection<T>
.
Czy jest gdzieś jakaś metoda użytkowa, która pozwoli mi szybko przekonwertować jedną na drugą? Chciałbym uniknąć tworzenia kilku foreach
pętli w moim kodzie dla tak prostej rzeczy.
19 answers
Z guawa możesz użyć List.zestawy newArrayList (Iterable) lub .newHashSet (Iterable) , wśród innych podobnych metod. To oczywiście skopiuje wszystkie elementy do pamięci. Jeśli to nie jest do przyjęcia, myślę, że Twój kod, który działa z nimi powinien przyjmować Iterable
, a nie Collection
. Guawa zdarza się również zapewnić wygodne metody robienia rzeczy, które można zrobić na Collection
za pomocą Iterable
(takie jak Iterables.isEmpty(Iterable)
lub Iterables.contains(Iterable, Object)
), ale implikacje wydajności są bardziej oczywiste.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-01 10:39:23
W JDK 8+, bez użycia dodatkowych libs:
Iterator<T> source = ...;
List<T> target = new ArrayList<>();
source.forEachRemaining(target::add);
Edit: powyższy jest dla Iterator
. Jeśli masz do czynienia z Iterable
,
iterable.forEach(target::add);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-17 02:14:56
Możesz również napisać własną metodę użytkową:
public static <E> Collection<E> makeCollection(Iterable<E> iter) {
Collection<E> list = new ArrayList<E>();
for (E item : iter) {
list.add(item);
}
return list;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-27 15:16:43
Zwięzłe rozwiązanie z Java 8 za pomocą java.util.stream
:
public static <T> List<T> toList(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-02 14:25:40
IteratorUtils
z commons-collections
mogą pomóc (chociaż nie obsługują generyków w najnowszej stabilnej wersji 3.2.1):
@SuppressWarnings("unchecked")
Collection<Type> list = IteratorUtils.toList(iterable.iterator());
Wersja 4.0 (która jest w tej chwili w migawce) obsługuje generyki i możesz pozbyć się @SuppressWarnings
.
Aktualizacja: sprawdź IterableAsList
z Cactoos .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-10 09:12:36
From Collection :
List<T> targetCollection = new ArrayList<T>();
CollectionUtils.addAll(targetCollection, iterable.iterator())
Oto pełne źródła tej metody użytkowej:
public static <T> void addAll(Collection<T> collection, Iterator<T> iterator) {
while (iterator.hasNext()) {
collection.add(iterator.next());
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-30 20:22:01
Nie zapominaj, że wszystkie zbiory są skończone, podczas gdy Iterable nie ma żadnych obietnic. Jeśli coś jest iteracyjne można uzyskać Iterator i to jest to.
for (piece : sthIterable){
..........
}
Zostanie rozszerzona do:
Iterator it = sthIterable.iterator();
while (it.hasNext()){
piece = it.next();
..........
}
To.hasNext () nie jest wymagane, aby kiedykolwiek zwrócić false. Tak więc w ogólnym przypadku nie można oczekiwać, aby być w stanie przekonwertować każdy Iterable do zbioru. Na przykład można iterację nad wszystkimi dodatnimi liczbami naturalnymi, iterację nad czymś z cyklami w nim, które wytwarzają te same wyniki w kółko, itp.
Inaczej: odpowiedź Atreya jest całkiem dobra.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-07 20:11:26
Używam FluentIterable.from(myIterable).toList()
dużo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-18 23:11:21
Natknąłem się na podobną sytuację, próbując pobrać List
z Project
s, zamiast domyślnego Iterable<T> findAll()
zadeklarowanego w CrudRepository
interfejsie. Tak więc, w moim interfejsie ProjectRepository
(który rozciąga się od CrudRepository
), po prostu zadeklarowałem metodę findAll()
, aby zwrócić List<Project>
zamiast Iterable<Project>
.
package com.example.projectmanagement.dao;
import com.example.projectmanagement.entities.Project;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface ProjectRepository extends CrudRepository<Project, Long> {
@Override
List<Project> findAll();
}
Jest to chyba najprostsze rozwiązanie, nie wymagające logiki konwersji ani użycia zewnętrznych bibliotek.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-30 04:14:53
To nie jest odpowiedź na twoje pytanie, ale uważam, że jest to rozwiązanie twojego problemu. Interfejs org.springframework.data.repository.CrudRepository
rzeczywiście posiada metody zwracające java.lang.Iterable
, ale nie powinieneś używać tego interfejsu. Zamiast tego użyj interfejsów podrzędnych, w Twoim przypadku org.springframework.data.mongodb.repository.MongoRepository
. Interfejs ten posiada metody zwracające obiekty typu java.util.List
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 12:04:08
Używam mojego niestandardowego narzędzia do tworzenia istniejącej kolekcji, jeśli jest dostępna.
Główna:
public static <T> Collection<T> toCollection(Iterable<T> iterable) {
if (iterable instanceof Collection) {
return (Collection<T>) iterable;
} else {
return Lists.newArrayList(iterable);
}
}
Najlepiej byłoby użyć ImmutableList, ale ImmutableCollection nie pozwala na NULL, które mogą przynieść niepożądane rezultaty.
Testy:
@Test
public void testToCollectionAlreadyCollection() {
ArrayList<String> list = Lists.newArrayList(FIRST, MIDDLE, LAST);
assertSame("no need to change, just cast", list, toCollection(list));
}
@Test
public void testIterableToCollection() {
final ArrayList<String> expected = Lists.newArrayList(FIRST, null, MIDDLE, LAST);
Collection<String> collection = toCollection(new Iterable<String>() {
@Override
public Iterator<String> iterator() {
return expected.iterator();
}
});
assertNotSame("a new list must have been created", expected, collection);
assertTrue(expected + " != " + collection, CollectionUtils.isEqualCollection(expected, collection));
}
Implementuję podobne narzędzia dla wszystkich podtypów kolekcji (Set,List,etc). Myślałem, że to już część guawy, ale jej nie znalazłem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-04 08:35:13
Jak tylko zadzwonisz contains
, containsAll
, equals
, hashCode
, remove
, retainAll
, size
albo toArray
, i tak musiałbyś przejść przez żywioły.
Jeśli od czasu do czasu wywołujesz tylko metody takie jak isEmpty
lub clear
, to myślę, że lepiej będzie, tworząc kolekcję leniwie. Możesz na przykład mieć Backup ArrayList
do przechowywania wcześniej iteracyjnych elementów.
Nie znam żadnej takiej klasy w żadnej bibliotece, ale powinno to być dość proste ćwiczenie do napisania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-20 20:29:35
W Javie 8 możesz to zrobić, aby dodać wszystkie elementy z Iterable
do Collection
i zwrócić je:
public static <T> Collection<T> iterableToCollection(Iterable<T> iterable) {
Collection<T> collection = new ArrayList<>();
iterable.forEach(collection::add);
return collection;
}
Zainspirowany przez @ Afreys odpowiedz.
Ponieważ RxJava jest młotkiem, a ten wygląda jak gwóźdź, możesz to zrobić
Observable.from(iterable).toList().toBlocking().single();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-15 07:57:52
Oto SSCCE na świetny sposób, aby to zrobić w Javie 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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-08 06:54:30
Dwie uwagi
- nie ma potrzeby konwertowania iterable do kolekcji, aby używać foreach loop - Iterable może być użyty w takiej pętli bezpośrednio, nie ma różnica składniowa, więc trudno zrozumieć, dlaczego w ogóle zadano pierwotne pytanie.
- sugerowany sposób konwersji Iterowalnej do kolekcji jest niebezpieczny (to samo dotyczy CollectionUtils) - nie ma gwarancji, że kolejne wywołania metody next () zwrócą różne instancje obiektów. Co więcej, ta troska nie jest czysta teoria. Np. implementacja Iterable używana do przekazywania wartości do metody reduction reduktora Hadoop zawsze zwraca tę samą instancję wartości, tylko z różnymi wartościami pól. Więc jeśli zastosujesz makeCollection z góry(lub CollectionUtils.addAll (Iterator)) otrzymasz kolekcję ze wszystkimi identycznymi elementami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-20 12:15:37
Try StickyList
from Cactoos :
List<String> list = new StickyList<>(iterable);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-20 17:35:49
Nie widziałem prostego rozwiązania jednowierszowego bez żadnych zależności. I proste użycie
List<Users> list;
Iterable<IterableUsers> users = getUsers();
// one line solution
list = StreamSupport.stream(users.spliterator(), true).collect(Collectors.toList());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-27 07:40:01
Możesz użyć kolekcji Eclipse :
Iterable<String> iterable = Arrays.asList("1", "2", "3");
MutableList<String> list = Lists.mutable.withAll(iterable);
MutableSet<String> set = Sets.mutable.withAll(iterable);
MutableSortedSet<String> sortedSet = SortedSets.mutable.withAll(iterable);
MutableBag<String> bag = Bags.mutable.withAll(iterable);
MutableSortedBag<String> sortedBag = SortedBags.mutable.withAll(iterable);
Możesz również przekonwertować {[2] } na LazyIterable
i użyć metod konwertera lub dowolnego innego dostępnego API.
Iterable<String> iterable = Arrays.asList("1", "2", "3");
LazyIterable<String> lazy = LazyIterate.adapt(iterable);
MutableList<String> list = lazy.toList();
MutableSet<String> set = lazy.toSet();
MutableSortedSet<String> sortedSet = lazy.toSortedSet();
MutableBag<String> bag = lazy.toBag();
MutableSortedBag<String> sortedBag = lazy.toSortedBag();
Wszystkie powyższe typy Mutable
rozszerzają java.util.Collection
.
Uwaga: jestem committerem Dla Kolekcji Eclipse.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-21 21:53:30