Bir değerden bir değere sıralı değerlerle List<Integer>
bir Integer[]
veya belki bir veya oluşturmanın kısa ve tatlı bir yolu var mı ?int[]
start
end
Yani, aşağıdakilerden daha kısa, ancak aşağıdakilerden 1'e eşdeğer bir şey :
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;
}
Guava kullanımı gayet iyi.
Güncelleme:
Performans analizi
Bu soru hem yerel Java 8 hem de üçüncü taraf kitaplıkları kullanarak birçok iyi yanıt aldığından, tüm çözümlerin performansını test edeceğimi düşündüm.
İlk test [1..10]
, aşağıdaki yöntemleri kullanarak 10 öğeden oluşan bir liste oluşturmayı test eder:
- classicArrayList : sorumda yukarıda verilen kod (ve esasen adarshr'ın cevabı ile aynı).
- eclipseCollections : Donald'ın Eclipse Collections 8.0'ı kullanarak aşağıdaki yanıtında verilen kod .
- guavaRange : aşağıdaki daveb'in cevabında verilen kod . Teknik olarak, bu bir yaratmaz,
List<Integer>
aksine birContiguousSet<Integer>
- amaIterable<Integer>
sırayla uyguladığından , çoğunlukla benim amaçlarım için çalışır. - intStreamRange : Vladimir'in aşağıdaki cevabında verilen kod
IntStream.rangeClosed()
, Java 8'de tanıtılan. - streamIterate : Catalin'in aşağıdaki yanıtında verilen
IntStream
ve Java 8'de tanıtılan işlevselliği de kullanan kod .
Aşağıda, 10 büyüklüğünde listelerle yukarıdakilerin tümü için saniye başına kilo işlemlerinin sonuçları (daha yüksek sayılar daha iyidir) verilmiştir:
... ve yine 10.000 büyüklüğündeki listeler için:
Bu son grafik doğrudur - Eclipse ve Guava dışındaki çözümler, tek bir piksel çubuğu bile alamayacak kadar yavaştır! Hızlı çözümler diğerlerinden 10.000 ila 20.000 kat daha hızlıdır.
Elbette burada olan şey, guava ve tutulma çözümlerinin gerçekte herhangi bir 10.000 öğe listesini gerçekleştirmemesidir - bunlar başlangıç ve bitiş noktaları etrafında sabit boyutlu sarmalayıcılardır. Her öğe, yineleme sırasında gerektiği gibi oluşturulur. Bu testte aslında yineleme yapmadığımız için, maliyet ertelendi. Diğer tüm çözümler aslında tam listeyi bellekte somutlaştırır ve yalnızca yaratım için bir kıyaslamada ağır bir bedel öder.
Biraz daha gerçekçi bir şey yapalım ve ayrıca tüm tam sayıları tekrarlayıp toplayalım. Dolayısıyla, IntStream.rangeClosed
varyant durumunda , kıyaslama şöyle görünür:
@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;
}
Burada, somutlaşmayan çözümler hala en hızlı olmasına rağmen, resimler çok değişiyor. İşte uzunluk = 10:
... ve uzunluk = 10.000:
Pek çok öğe üzerindeki uzun yineleme, işleri çok fazla eşitler, ancak tutulma ve guava, 10.000 öğe testinde bile iki katından daha hızlı kalır.
Öyleyse, gerçekten bir List<Integer>
tutulma koleksiyonları istiyorsanız en iyi seçenek gibi görünüyor - ancak tabii ki akışları daha doğal bir şekilde kullanırsanız (örneğin, unutmak .boxed()
ve ilkel alanda bir azalma yapmak) muhtemelen tüm bunlardan daha hızlı sonuçlanacaksınız. varyantları.
1 Belki hata işleme haricinde, örn. end
< begin
İse veya boyut bazı uygulama veya JVM sınırlarını aşarsa (örn., 2^31-1
.