Czy istnieje krótki i przyjemny sposób generowania a List<Integer>
, a może Integer[]
lub lub int[]
z sekwencyjnymi wartościami od jakiejś start
wartości do end
wartości?
To znaczy coś krótszego niż, ale równoważne 1 z następującego:
void List<Integer> makeSequence(int begin, int end) {
List<Integer> ret = new ArrayList<>(end - begin + 1);
for (int i=begin; i<=end; i++) {
ret.add(i);
}
return ret;
}
Używanie guawy jest w porządku.
Aktualizacja:
Analiza wydajności
Ponieważ to pytanie otrzymało kilka dobrych odpowiedzi, zarówno przy użyciu natywnych bibliotek Java 8, jak i bibliotek innych firm, pomyślałem, że przetestuję wydajność wszystkich rozwiązań.
Pierwszy test polega po prostu na przetestowaniu tworzenia listy 10 elementów [1..10]
za pomocą następujących metod:
- classicArrayList : kod podany powyżej w moim pytaniu (i zasadniczo taki sam jak odpowiedź adarshr).
- eclipseCollections : kod podany w odpowiedzi Donalda poniżej przy użyciu Eclipse Collections 8.0.
- guavaRange : kod podany w odpowiedzi daveb poniżej. Technicznie rzecz biorąc, nie tworzy to,
List<Integer>
ale raczejContiguousSet<Integer>
- ale ponieważ wdraża sięIterable<Integer>
w kolejności, działa głównie do moich celów. - intStreamRange : kod podany w odpowiedzi Vladimira poniżej, który używa
IntStream.rangeClosed()
- który został wprowadzony w Javie 8. - streamIterate : kod podany w poniższej odpowiedzi Catalina, który również wykorzystuje
IntStream
funkcjonalność wprowadzoną w Javie 8.
Oto wyniki w kilo operacjach na sekundę (wyższe liczby są lepsze), dla wszystkich powyższych z listami o rozmiarze 10:
... i jeszcze raz dla list o rozmiarze 10000:
Ten ostatni wykres jest poprawny - rozwiązania inne niż Eclipse i Guava są zbyt wolne, aby uzyskać nawet pojedynczy pasek pikseli! Szybkie rozwiązania są od 10 000 do 20 000 razy szybsze niż pozostałe.
Oczywiście chodzi tutaj o to, że rozwiązania z guawy i zaćmienia w rzeczywistości nie materializują żadnej listy 10 000 elementów - są po prostu opakowaniami o stałym rozmiarze wokół punktów początkowych i końcowych. Każdy element jest tworzony w razie potrzeby podczas iteracji. Ponieważ w rzeczywistości nie wykonujemy iteracji w tym teście, koszt jest odroczony. Wszystkie inne rozwiązania faktycznie materializują pełną listę w pamięci i płacą wysoką cenę w benchmarku tylko do tworzenia.
Zróbmy coś bardziej realistycznego, a także powtórzmy wszystkie liczby całkowite, sumując je. Czyli w przypadku IntStream.rangeClosed
wariantu benchmark wygląda następująco:
@Benchmark
public int intStreamRange() {
List<Integer> ret = IntStream.rangeClosed(begin, end).boxed().collect(Collectors.toList());
int total = 0;
for (int i : ret) {
total += i;
}
return total;
}
Tutaj obraz bardzo się zmienia, choć wciąż najszybsze są niematerialne rozwiązania. Oto długość = 10:
... i długość = 10000:
Długa iteracja wielu elementów bardzo wyrównuje sytuację, ale zaćmienie i guawa pozostają ponad dwukrotnie szybsze nawet w teście 10000 elementów.
Więc jeśli naprawdę chcesz List<Integer>
, kolekcje zaćmienia wydają się najlepszym wyborem - ale oczywiście, jeśli używasz strumieni w bardziej natywny sposób (np. Zapominając .boxed()
i redukując prymitywną domenę), prawdopodobnie skończysz szybciej niż wszystkie te warianty.
1 Być może z wyjątkiem obsługi błędów, np. If end
< begin
, lub jeśli rozmiar przekracza pewne limity implementacji lub JVM (np. Tablice większe niż 2^31-1
.
źródło
Odpowiedzi:
Dzięki Java 8 jest to tak proste, że nie wymaga już nawet oddzielnej metody:
źródło
Cóż, ten jeden liniowiec może się kwalifikować (używa zakresów guawy )
Nie tworzy to
List<Integer>
, aleContiguousSet
oferuje taką samą funkcjonalność, w szczególności implementację,Iterable<Integer>
która umożliwiaforeach
implementację w taki sam sposób, jakList<Integer>
.W starszych wersjach (gdzieś przed Guava 14) możesz użyć tego:
Oba produkują:
źródło
asList()
tam, chyba że naprawdę potrzebujeszList
...ContiguousSet
wyprodukowany przezasSet
jest lekki (potrzebuje tylko zakresu i domeny), aleasList()
utworzę listę, która faktycznie przechowuje wszystkie elementy w pamięci (obecnie).Range
istnieje, ale nie maRanges
i oni zlikwidowali tęasSet
metodę. W mojej starszej wersjiasSet
jest przestarzały i wygląda na to, że go usunęli. Zakresy najwyraźniej mają być używane tylko do ciągłych kolekcji i wymusili to, chociaż uwielbiam to rozwiązanie.Następująca jednoliniowa wersja Java 8 wygeneruje [1, 2, 3 ... 10]. Pierwszy argument
iterate
jest pierwszym numerem w sekwencji, a pierwszym argumentemlimit
jest ostatnia liczba.źródło
Możesz użyć
Interval
klasy z kolekcji Eclipse .Interval
Klasa jest leniwy, więc nie przechowuje wszystkie wartości.Twoja metoda mogłaby zostać zaimplementowana w następujący sposób:
Jeśli chcesz uniknąć oznaczania liczb całkowitych jako liczb całkowitych, ale nadal chciałbyś mieć strukturę listy, możesz użyć
IntList
zIntInterval
kolekcjami Eclipse.IntList
ma metodysum()
,min()
,minIfEmpty()
,max()
,maxIfEmpty()
,average()
imedian()
dostępne w interfejsie.Aktualizacja dla przejrzystości: 27.11.2017
An
Interval
jestList<Integer>
, ale jest leniwy i niezmienny. Jest to niezwykle przydatne do generowania danych testowych, zwłaszcza jeśli masz do czynienia ze zbiorami. Jeśli chcesz, możesz łatwo skopiować interwał DoList
,Set
lubBag
w sposób następujący:Jest
IntInterval
to,ImmutableIntList
co się rozciągaIntList
. Posiada również metody konwertera.An
Interval
iIntInterval
nie mają tej samejequals
umowy.Aktualizacja kolekcji Eclipse 9.0
Możesz teraz tworzyć pierwotne kolekcje z pierwotnych strumieni. Istnieją
withAll
iofAll
metody w zależności od twoich preferencji. Jeśli jesteś ciekawy, wyjaśnię, dlaczego mamy tutaj oba . Te metody istnieją dla zmiennych i niezmiennych list Int / Long / Double, zestawów, worków i stosów.Uwaga: jestem promotorem Eclipse Collections
źródło
To jest najkrótszy, jaki mogłem uzyskać używając Core Java.
źródło
for(int i = begin; i <= end; ret.add(i++));
:)ret.add(i)
części do inkrementacji pętli for sprawia, że jest to „krótsze”. Myślę, że zgodnie z tą logiką, gdybym napisał to wszystko w jednym wierszu, byłby krótszy :)Możesz użyć zakresów guawy
Możesz uzyskać
SortedSet
za pomocąźródło
To jest najkrótszy, jaki udało mi się znaleźć.
Wersja listy
Wersja tablicowa
źródło
Ten może działać dla Ciebie ....
źródło