ArrayList için başlangıç ​​boyutu


257

Bir ArrayList için başlangıç ​​boyutunu aşağıdakileri yaparak ayarlayabilirsiniz:

ArrayList<Integer> arr=new ArrayList<Integer>(10);

Ancak yapamazsın

arr.add(5, 10);

çünkü sınırların dışında bir istisnaya neden olur.

Ayrılan alana erişemiyorsanız, bir başlangıç ​​boyutu belirlemenin faydası nedir?

Ekle işlevi, add(int index, Object element)dizin 10'a eklemiyorum diye tanımlanır .


52
Aslında, bir listenin n-1 öğesini yapabilmeniz için en az n öğenin eklenmesi gerektiği belgelerden belli değildir . set/add
Algı

5
Algı: Açık olup olmadığını bilmiyorum, ama belirtildi. JavaDoc dikkatle okunmalıdır.Throws: IndexOutOfBoundsException - dizin aralık dışındaysa (index <0 || index> = size ()).
Natix

3
"Konstruktlar belirtilen başlangıç kapasitesiyle boş bir liste" Hm, yapıcı, bir indeks 5. orada olamaz boş listesinin kavramını alarak diyor Ama bu olabilir ... ilk bakışta görünmeyebilir konusunda hemfikir
quaylar

12
Bir diziyi belirli bir değere başlatırsanız, bu değerin altındaki endekslerin kullanılabilir olduğunu varsayacağınızı söylemek de adil olur - ve bu bir ArrayList. Şahsen, belirli endekslere bir şeyler koyabileceğim bir boyut belirlememe izin verecek bir yöntem istiyorum. Bu yöntem kayda değer görünmüyor.
Andrew Wyld

1
Hangi numbskull koleksiyonları bu şekilde tasarladı ?! Bu, değişken uzunluktaki elemanlara (yani her dizinin farklı bir uzunluğa sahip olabileceği ArrayList <String []>) bir yapının paralel somutlaştırılması için fazladan çalışmayı zorlar. Bellek zaten ayrılmışsa, N öğelerini ekledikten sonra listenin yeniden tahsis edilmesine gerek kalmazsa, bu indekslere en baştan doğrudan erişilebilir olmalıdır. Oracle'da hiç kimse C / C ++, C #, Objective C ve Swift'den sonra bu modeli öğrenmedi mi ?!
patrickjp93

Yanıtlar:


387

Dizi listesinin boyutunu kapasitesiyle karıştırıyorsunuz:

  • Boyut listesindeki elemanların sayısı olduğu;
  • kapasite liste potansiyel iç yapılarını yeniden tahsis etmeden alabildiği kaç eleman.

Aradığınızda new ArrayList<Integer>(10), listenin boyutunu değil başlangıç kapasitesini ayarlarsınız . Başka bir deyişle, bu şekilde oluşturulduğunda dizi listesi ömrünü boşaltır.

Dizi listesine on öğe eklemenin bir yolu bir döngü kullanmaktır:

for (int i = 0; i < 10; i++) {
  arr.add(0);
}

Bunu yaptıktan sonra, endeksler 0..9'daki elemanları değiştirebilirsiniz.


51
+1: Daha kısa bir döngü: while(arr.size() < 10) arr.add(0);En azından boyutun olması gerektiğini söylemek faydalı olabilir 10. örneğin kullanabilirsinizarr.set(9, n);
Peter Lawrey

10
+1: Harika yanıt, yapabilseydim +10 verirdim. Api'den neden tek bir yapıcı çağrısında başlangıç ​​boyutunu ve başlangıç ​​kapasitesini İKİ olarak ayarlayamayacağınız hemen belli değildir. Bir çeşit api okumak zorunda ve "Ah, sanırım ArrayList bunu yapmak için bir yöntem veya yapıcı yok"
demek

@PeterLawrey Kodunuz daha kısa olabilir, ancak her döngü yinelemesi için yalnızca bir tane değil, iki yöntem çağrısı içerir.
nöralmer

@neuralmer Size () ve add () inline olmasını beklerdim, böylece çalışma zamanında gerçek bir yöntem çağrısı gerçekleşmez.
Peter Lawrey

109

Önceden tanımlanmış bir boyuta sahip bir liste istiyorsanız şunları da kullanabilirsiniz:

List<Integer> arr = Arrays.asList(new Integer[10]);

11
Burada hafif bir dezavantaj, sonuçta Listboşlarla doludur. Guava Ints.asList(new int[10])ile listeyi 0s ile başlatabiliriz . Temiz desen olsa da, örnek için teşekkürler.
dimo414

1
Sorular ArrayList <E> hakkında konuşuyor. <E> Listesini kullanıyorsunuz. Kimse bunu gözlemlemedi ??? Dahası, bu alakasız cevabı iptal ettiler ! Cevabınızı küçümsemiyorum çünkü asla yapmıyorum. Basitçe ... Godssake!
Apostolos

3
@Apostolos arabirimin ArrayListbir uygulamasıdır Listve Arrays.asListbir ArrayList. Ben polimorfizme bakmanızı öneririm.
Liam Potter

Bu, sabit boyutlu bir Liste döndürür. Daha fazla eleman eklemeye çalışıyorUnsupportedOperationException
Koray Tugay

47

Collections.fill (list, obj) kullanmak istiyorsanız; listeyi tekrarlanan bir nesne ile doldurmak için alternatif olarak

ArrayList<Integer> arr=new ArrayList<Integer>(Collections.nCopies(10, 0));

satır ArrayList'inize 10 kez 0 kopyalar


20

Kapasite , bir ait ArrayListolan ile aynı değildir boyutu . Boyut , ArrayList(ve diğer herhangi bir öğede bulunan öğe sayısına eşittir)List uygulamalarda) .

Kapasitesi olarak internal elemanlarını depolamak için kullanılan alttaki dizinin sadece uzunluğu ArrayListve her zaman daha yüksek olan ya da eşit boyutta listesinin.

set(index, element)Listeyi çağırırken , dizi uzunluğu (= kapasite) (uygulama özelliğine özgü) değil index, liste öğelerinin gerçek sayısı (= boyut) (kodunuzda sıfırdır, bu nedenle AIOOBEatılır) ile ilgilidir. -eArrayList ).

setYöntem için ortaktır Listgibi uygulamalarda, LinkedListaslında bir dizi tarafından uygulanabilir değildir, ancak girişlerin bağlı bir zincir gibi.

Düzenleme : Aslında add(index, element)yöntemi kullanmak değil set(index, element), ama ilke burada aynı.


10

Dizine sahip öğeleri eklemek istiyorsanız, bunun yerine bir dizi kullanabilirsiniz.

    String [] test = new String[length];
    test[0] = "add";

5
OP başlangıçta bir Liste kullanmak istemedi ... bir dizi değil.
Stephan

9

10, AL'nin başlangıç ​​kapasitesidir, boyutu değil (0'dır). Çok sayıda öğeye sahip olacağınız zaman, ilk kapasiteyi yüksek bir değere değinmelisiniz, çünkü eleman eklemeye devam ederken kapasiteyi genişletme yükünü ortadan kaldırır.


6

Sorunuza kesin bir cevap olurdu sanırım:

ArrayList üzerinde başlangıç ​​boyutu ayarlamak nr değerini azaltır. dahili bellek yeniden tahsisinin gerçekleşmesi gerekir. Liste bir dizi tarafından desteklenir. Başlangıç ​​kapasitesini 0 belirtirseniz, zaten bir öğenin ilk eklemesinde dahili dizinin yeniden boyutlandırılması gerekir. Listenizin kaç öğe tutacağı hakkında yaklaşık bir fikriniz varsa, ilk kapasitenin ayarlanması nr değerini azaltır. listeyi kullanırken yapılan bellek yeniden ayırma işlemlerinin yüzdesi.


3

Bu birine yardımcı olabilir -

ArrayList<Integer> integerArrayList = new ArrayList<>(Arrays.asList(new Integer[10]));

3

Buna geç kalıyorum , ancak Java 8'den sonra , kişisel olarak şu StreamAPI yaklaşımını daha özlü buluyorum ve kabul edilen cevaba bir alternatif olabilir .

Örneğin,

Arrays.stream(new int[size]).boxed().collect(Collectors.toList())

burada sizearzu edilen Listboyut ve olmadan dezavantajı burada belirtilen , bütün elemanlar Listolarak başlatılır0 .

(Hızlı bir arama yaptım ve gönderilen streamyanıtlarda görmedim - bu cevabın gereksiz olup olmadığını bana bildirmekten çekinmeyin ve kaldırabilirim)


1

Şu anda listenizde hiç öğe yok, bu nedenle listenin 5. dizinine mevcut olmadığında ekleyemezsiniz. Listenin kapasitesini mevcut boyutuyla karıştırıyorsunuz.

Sadece ara:

arr.add(10)

ArrayList'inize Tamsayı eklemek için


1

Arraylistinizin kapasitesi 10 olsa da, gerçek listenin burada hiçbir öğesi yoktur. Add yöntemi, gerçek listeye bir öğe eklemek için kullanılır. Öğesi olmadığından, 5 dizinine bir öğe ekleyemezsiniz.


1

10 öğe eklemek istiyorsanız bunu ArrayListdeneyebilirsiniz:

for (int i = 0; i < 10; i++)
    arr.add(i);

Zaten bir dizi boyutu değişkeni bildirdiyseniz, değişkeni size'10' yerine kullanırsınız


1

Benzer bir sorunla karşı karşıya kaldım ve sadece arrayList öğesinin Liste arabiriminin yeniden boyutlandırılabilir bir dizi uygulaması olduğunu bilerek, herhangi bir noktaya öğe ekleyebileceğinizi, ancak en azından başlangıç ​​boyutunu tanımlama seçeneğine sahip olduğunuzu umuyorum. Her neyse, önce bir dizi oluşturabilir ve bunu aşağıdaki gibi bir listeye dönüştürebilirsiniz:

  int index = 5;
  int size = 10;

  Integer[] array = new Integer[size];
  array[index] = value;
  ...
  List<Integer> list = Arrays.asList(array);

veya

  List<Integer> list = Arrays.asList(new Integer[size]);
  list.set(index, value);

0

ArrayList myList = yeni ArrayList (10);

//  myList.add(3, "DDD");
//  myList.add(9, "III");
    myList.add(0, "AAA");
    myList.add(1, "BBB");

    for(String item:myList){
        System.out.println("inside list : "+item);
    }

/ * Arraylistin başlangıç ​​kapasitesinin, dahili olarak vites değiştirme zamanından tasarruf etmekten başka bir şey olmadığını beyan etmek; öğeyi dahili olarak eklediğimizde, kapasiteyi artırmak için kapasiteyi kontrol eder, öğeyi başlangıçta 0 dizinine sonra 1'e ekleyebilirsiniz. * /


0

İki sentim Stream. Bence kullanmak daha iyi

IntStream.generate(i -> MyClass.contruct())
         .limit(INT_SIZE)
         .collect(Collectors.toList());

başlangıç ​​değerlerini koyma esnekliği ile.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.