Mam tablicę prymitywów, na przykład dla int, int [] foo. Może to być mały rozmiar lub nie.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
Jaki jest najlepszy sposób na stworzenie Iterable<Integer>
z tego pliku ?
Iterable<Integer> fooBar = convert(foo);
Uwagi:
Proszę nie odpowiadać za pomocą pętli (chyba że możesz dobrze wyjaśnić, w jaki sposób kompilator zrobił z nimi coś inteligentnego?)
Zwróć też na to uwagę
int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);
Nawet się nie skompiluje
Type mismatch: cannot convert from List<int[]> to List<Integer>
Sprawdź także, dlaczego tablicy nie można przypisać do iterowalnej? zanim odpowiesz.
Ponadto, jeśli używasz jakiejś biblioteki (np. Guava), wyjaśnij, dlaczego jest najlepsza. (Bo to od Google nie jest pełną odpowiedzią: P)
Wreszcie, ponieważ wydaje się, że jest zadanie domowe na ten temat, unikaj publikowania kodu pracy domowej.
Odpowiedzi:
Chociaż musisz użyć
Integer
tablicy (nieint
tablicy), aby to zadziałało.W przypadku prymitywów możesz użyć guawy:
Dla Java8: (z odpowiedzi Jin Kwon)
źródło
int
, a nieInteger
2)List
już jest,Iterable
więc trzecia linijka jest bezcelowa.tylko moje 2 centy:
źródło
Iterator<Character>
zString
. Wdrożenie własnegoIterator
wydaje się jedynym sposobem na uniknięcie niepotrzebnego iterowania przez wszystkie wartości w celu konwersji z typu obiektu do typu pierwotnego (Ints.asList()
na przykład przez Guava ), tylko po to, aby móc uzyskać wynikIterator
z tego,List
który został utworzony.Dzięki Java 8 możesz to zrobić.
źródło
Guava dostarcza żądany adapter jako Int.asList () . Jest odpowiednikiem dla każdego rodzaju prymitywnego w dodatkowej klasy, na przykład,
Booleans
dlaboolean
itpPowyższe sugestie dotyczące użycia
Arrays.asList
nie będą działać, nawet jeśli zostaną skompilowane, ponieważ otrzymaszIterator<int[]>
zamiastIterator<Integer>
. Dzieje się tak, że zamiast tworzyć listę wspieraną przez twoją tablicę, utworzyłeś 1-elementową listę tablic, zawierającą twoją tablicę.źródło
Miałem ten sam problem i rozwiązałem go w ten sposób:
Sam iterator jest leniwy,
UnmodifiableIterator
ale właśnie tego potrzebowałem.źródło
W Javie 8 lub nowszym
Iterable
zwraca funkcjonalny interfejsIterator
. Więc możesz to zrobić.źródło
Przede wszystkim mogę się tylko zgodzić, że
Arrays.asList(T...)
jest to zdecydowanie najlepsze rozwiązanie dla typów Wrapper lub tablic z innymi niż pierwotne typy danych. Ta metoda wywołuje konstruktor prostej prywatnejAbstractList
implementacji statycznej wArrays
klasie, która w zasadzie zapisuje podane odwołanie do tablicy jako pole i symuluje listę, zastępując potrzebne metody.Jeśli możesz wybrać typ pierwotny lub typ Wrapper dla swojej tablicy, użyłbym typu Wrapper w takich sytuacjach, ale oczywiście nie zawsze jest on przydatny lub wymagany. Byłyby tylko dwie możliwości, które możesz zrobić:
1) Możesz utworzyć klasę ze statyczną metodą dla każdej pierwotnej tablicy typu danych (
boolean, byte, short, int, long, char, float, double
zwracającIterable<
WrapperType>
. Te metody używałyby anonimowych klasIterator
(pozaIterable
), które mogą zawierać odwołanie do argumentu metody zawierającej (na przykładint[]
) jako pole w celu zaimplementowania metod.-> To podejście jest wydajne i oszczędza pamięć (z wyjątkiem pamięci nowo utworzonych metod, chociaż użycie
Arrays.asList()
zajmie pamięć w ten sam sposób)2) Ponieważ tablice nie mają metod (jak do odczytu z boku z linkiem), nie mogą też zapewnić
Iterator
instancji. Jeśli naprawdę jesteś zbyt leniwy, aby pisać nowe klasy, musisz użyć instancji już istniejącej klasy, która implementuje,Iterable
ponieważ nie ma innego wyjścia niż utworzenie instancjiIterable
lub podtyp.JEDYNY sposób na utworzenie istniejącej implementacji pochodnej kolekcji
Iterable
polega na użyciu pętli (z wyjątkiem używania klas anonimowych, jak opisano powyżej) lub utworzeniu instancjiIterable
klasy implementującej, której konstruktor zezwala na tablicę typu pierwotnego (ponieważObject[]
nie zezwala na tablice z elementami typu pierwotnego), ale o ile wiem, API Java nie ma takiej klasy.Powód pętli można łatwo wyjaśnić:
dla każdej kolekcji potrzebujesz Obiekty, a pierwotne typy danych nie są obiektami. Obiekty są znacznie większe niż typy pierwotne, dlatego wymagają dodatkowych danych, które muszą zostać wygenerowane dla każdego elementu tablicy typów pierwotnych. Oznacza to, że jeśli dwa z trzech sposobów (używanie
Arrays.asList(T...)
lub używanie istniejącej kolekcji) wymagają agregacji obiektów, musisz utworzyć dla każdej pierwotnej wartości swojejint[]
w szyku obiekt opakowania. Trzeci sposób użyłby tablicy w takiej postaci, w jakiej jest, i użyłby jej w klasie anonimowej, ponieważ uważam, że jest to preferowane ze względu na dużą wydajność.Istnieje również trzecia strategia wykorzystująca
Object
argument jako argument dla metody, w której chcesz użyć tablicy lubIterable
która wymagałaby sprawdzenia typu, aby dowiedzieć się, jaki typ ma argument, jednak nie polecałbym tego w ogóle, ponieważ zwykle musisz weź pod uwagę, że Object nie zawsze ma wymagany typ i że w niektórych przypadkach potrzebujesz osobnego kodu.Podsumowując, jest to wina problematycznego systemu typów ogólnych w Javie, który nie pozwala na użycie typów pierwotnych jako typów ogólnych, co pozwoliłoby zaoszczędzić dużo kodu, używając prostego
Arrays.asList(T...)
. Więc musisz zaprogramować taką metodę dla każdej tablicy typów pierwotnych (która w zasadzie nie robi różnicy w pamięci używanej przez program w C ++, który utworzyłby dla każdego użytego argumentu typu oddzielną metodę.źródło
Możesz użyć
IterableOf
od Cactoos :Następnie możesz przekształcić go w listę za pomocą
ListOf
:Lub po prostu to:
źródło
Chociaż podobna odpowiedź została już opublikowana, myślę, że powód użycia nowego PrimitiveIterator.OfInt nie był jasny. Dobrym rozwiązaniem jest użycie Java 8 PrimitiveIterator, ponieważ jest ona wyspecjalizowana w prymitywnych typach int (i pozwala uniknąć dodatkowej kary za boxing / unboxing):
Ref: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html
źródło
W java8 strumień IntSteam może być opakowany w strumień liczb całkowitych.
Myślę, że wydajność ma znaczenie w zależności od rozmiaru tablicy.
źródło