W mojej aplikacji korzystam z biblioteki innej firmy (dokładniej Spring Data dla MongoDB).
Metody tej biblioteki zwracają się Iterable<T>
, podczas gdy reszta mojego kodu oczekuje Collection<T>
.
Czy jest gdzieś jakaś metoda narzędziowa, która pozwoli mi szybko przekonwertować jedną na drugą? Chciałbym uniknąć tworzenia kilkuforeach
pęków w moim kodzie dla tak prostej rzeczy.
java
collections
Ula Krukar
źródło
źródło
Odpowiedzi:
Z Guava możesz użyć Lists.newArrayList (Iterable) lub Sets.newHashSet (Iterable) , wśród innych podobnych metod. To oczywiście skopiuje wszystkie elementy do pamięci. Jeśli to nie jest dopuszczalne, uważam, że twój kod, który z nimi współpracuje, powinien
Iterable
raczej zająć niżCollection
. Zdarza się również, że Guava zapewnia wygodne metody robienia rzeczy, które można wykonać zaCollection
pomocąIterable
(takich jakIterables.isEmpty(Iterable)
lubIterables.contains(Iterable, Object)
), ale implikacje dotyczące wydajności są bardziej oczywiste.źródło
Lists.newArrayList(Iterable).clear()
operacja liniowa czy stała?Collection
albo nie można zaimplementować dla widoku,Iterable
albo nie będzie wydajna, nie ma dla mnie sensu, aby to robić.Iterables.concat()
ale daje toIterable
, a nieCollection
:(Iterables.concat()
. Dłuższa odpowiedź dajeCollection
... Zastanawiam się, dlaczego nie jest to częściej obsługiwane?W JDK 8+, bez korzystania z dodatkowych bibliotek:
Edycja: Powyższy jest dla
Iterator
. Jeśli masz do czynieniaIterable
,źródło
iterable.forEach(target::add);
Możesz również napisać własną metodę narzędzia:
źródło
Iterable
doCollection
jest jedynym problemem, wolę takie podejście niż importowanie dużej biblioteki zbiorów zewnętrznych.Zwięzłe rozwiązanie z Javą 8 przy użyciu
java.util.stream
:źródło
IteratorUtils
zcommons-collections
IteratorUtils.toList()
używa iteratora w sposób wcześniejszy niż Java 5, aby dodawać elementy jeden po drugim do nowo utworzonej listy. Prosty i prawdopodobnie najszybszy, ale dodaje 734 kB do twojego pliku binarnego i możesz to zrobić sam, jeśli uważasz, że ta metoda jest najlepsza.IteratorUtils
zcommons-collections
może pomóc (chociaż nie obsługują one generycznych w najnowszej stabilnej wersji 3.2.1):Wersja 4.0 (która jest obecnie w SNAPSHOT) obsługuje generyczne i możesz się ich pozbyć
@SuppressWarnings
.Aktualizacja: Sprawdź
IterableAsList
od Cactoos .źródło
IterableUtils.toList(Iterable)
metoda wygodna i stosowanaIteratorUtils
pod maską, ale także zerowa (w przeciwieństwie doIteratorUtils.toList
).Z kolekcjiUtils :
Oto pełne źródła tej metody narzędzia:
źródło
Lists.newArrayList(someIterable).clear()
operacja liniowa czy stała?addAll
, jak sama nazwa wskazuje, kopiuje wartości iteratora jedna po drugiej; tworzy kopię zamiast widoku.CollectionUtils
pominięcia tworzenia kolekcji w dodatkowej linii.Nie zapominając o tym, że wszystkie kolekcje są skończone, a Iterable nie ma żadnych obietnic. Jeśli coś jest Iterowalne, możesz dostać Iterator i to wszystko.
zostanie rozszerzony do:
it.hasNext () nie musi nigdy zwracać wartości false. Dlatego w ogólnym przypadku nie można oczekiwać, że będzie można przekonwertować każdy Iterable na kolekcję. Na przykład możesz iterować po wszystkich dodatnich liczbach naturalnych, iterować po czymś z cyklami, które dają te same wyniki w kółko itp.
W przeciwnym razie odpowiedź Atrey jest całkiem dobra.
źródło
Używam
FluentIterable.from(myIterable).toList()
dużo.źródło
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 ma metody, które zwracają,java.lang.Iterable
ale nie powinieneś używać tego interfejsu. Zamiast tego, w twoim przypadku, użyj interfejsów podrzędnychorg.springframework.data.mongodb.repository.MongoRepository
. Ten interfejs ma metody zwracające obiekty typujava.util.List
.źródło
Używam mojego niestandardowego narzędzia, by rzutować istniejącą kolekcję, jeśli jest dostępna.
Główny:
Idealnie powyższe użyłoby ImmutableList, ale ImmutableCollection nie dopuszcza wartości zerowych, które mogą dawać niepożądane wyniki.
Testy:
Implementuję podobne narzędzia dla wszystkich podtypów kolekcji (zestaw, lista itp.). Sądzę, że byłyby już częścią Guawy, ale nie znalazłem tego.
źródło
Jak najszybciej zadzwonić
contains
,containsAll
,equals
,hashCode
,remove
,retainAll
,size
lubtoArray
, że pan musiał przemierzać elementy tak.Jeśli od czasu do czasu wywołujesz tylko metody takie jak
isEmpty
lubclear
, przypuszczam, że lepiej byłoby, gdybyś utworzył kolekcję leniwie. Możesz na przykład mieć wsparcieArrayList
do przechowywania wcześniej iterowanych elementów.Nie znam żadnej takiej klasy w żadnej bibliotece, ale napisanie jej powinno być dość prostym ćwiczeniem.
źródło
W Javie 8 możesz to zrobić, aby dodać wszystkie elementy od
Iterable
doCollection
i zwrócić:Zainspirowany odpowiedzią @Afreys.
źródło
Ponieważ RxJava jest młotkiem, a ten rodzaj przypomina gwóźdź, możesz to zrobić
źródło
Oto SSCCE za świetny sposób na zrobienie tego w Javie 8
źródło
Dwie uwagi
źródło
Natknąłem się w podobnej sytuacji, starając się sprowadzić
List
zProject
S, raczej niż domyślneIterable<T> findAll()
zadeklarowane wCrudRepository
interfejsie. Tak więc w moimProjectRepository
interfejsie (który rozszerza sięCrudRepository
) po prostu zadeklarowałemfindAll()
metodę zwróceniaList<Project>
zamiastIterable<Project>
.To chyba najprostsze rozwiązanie, które nie wymaga logiki konwersji ani korzystania z zewnętrznych bibliotek.
źródło
Spróbuj
StickyList
z Cactoos :źródło
Nie widziałem prostego rozwiązania jednoliniowego bez żadnych zależności. Jestem prosty w użyciu
źródło
Możesz korzystać z fabryk kolekcji Eclipse :
Możesz także przekonwertować na
Iterable
aLazyIterable
i użyć metod konwertera lub dowolnego innego dostępnego API.Wszystkie powyższe
Mutable
typy rozszerzają sięjava.util.Collection
.Uwaga: jestem osobą odpowiedzialną za kolekcje Eclipse.
źródło