Arrays.asList (dizi) ve yeni ArrayList <Integer> (Arrays.asList (dizi)) arasındaki fark


119

Arasındaki fark nedir

1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

iatamsayı dizisi nerede .

Bazı işlemlere izin verilmediğini öğrendim list2. neden böyle bellekte nasıl saklanır (referanslar / kopya)?

Listeleri karıştırdığımda list1orijinal diziyi etkilemiyor ama etkiliyor list2. Ama yine list2de biraz kafa karıştırıcı.

Nasıl ArrayListyeni oluşturmasını liste farklıdır için upcasted ediliyorArrayList

list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));

2
Google Guava'nın seçeneğine bakmanızı öneririm . Lists.newArrayList(ia)ilk seçenek gibi bağımsız bir kopya yapar. Basitçe daha genel ve bakmak daha iyidir.
qben

Yanıtlar:


228
  1. İlk önce, bunun ne yaptığını görelim:

    Arrays.asList(ia)

    Bir dizi alır iave uygulayan bir sarmalayıcı oluşturur List<Integer>, bu da orijinal diziyi liste olarak kullanılabilir hale getirir. Hiçbir şey kopyalanmaz ve tümü, yalnızca tek bir sarmalayıcı nesnesi oluşturulur. Liste sarmalayıcısındaki işlemler orijinal diziye yayılır. Bu, liste sarmalayıcısını karıştırırsanız, orijinal dizinin de karıştırılacağı, bir öğenin üzerine yazarsanız, orijinal dizinin üzerine yazılacağı anlamına gelir. Elbette List, sarmalayıcıda ekleme veya ekleme gibi bazı işlemlere izin verilmez. öğeleri listeden kaldırırsanız, yalnızca öğeleri okuyabilir veya üzerine yazabilirsiniz.

    Liste sarmalayıcısının genişlemediğini unutmayın ArrayList- bu farklı bir tür nesnedir. ArrayListlerin kendi iç dizileri vardır, bu dizileri içinde saklanırlar ve iç dizileri yeniden boyutlandırabilirler. Sarmalayıcı kendi iç dizisine sahip değildir, sadece işlemleri kendisine verilen diziye yayar.

  2. Öte yandan, daha sonra yeni bir dizi oluşturursanız

    new ArrayList<Integer>(Arrays.asList(ia))

    daha sonra ArrayListorijinalin tam ve bağımsız bir kopyası olan yenisini yaratırsınız. Burada kullanarak Arrays.asListda sarıcı oluşturmanıza rağmen , sadece yeninin yapımı sırasında kullanılır ArrayListve daha sonra çöp olarak toplanır. Bu yeninin yapısı ArrayList, orijinal diziden tamamen bağımsızdır. Aynı öğeleri içerir (hem orijinal dizi hem de bu yeni ArrayList, bellekteki aynı tam sayılara başvurur), ancak referansları tutan yeni, dahili bir dizi oluşturur. Dolayısıyla, onu karıştırdığınızda, öğe eklediğinizde, kaldırdığınızda vb., Orijinal dizi değişmez.


9
@Dineshkumar Bir sarmalayıcı, bir sınıf için bir arabirimi başka bir arabirime çeviren bir tasarım modelidir. Bkz sargı model makale. | Nereye yayına ihtiyacınız var? List<Integer>Değişken türleriniz (veya yöntem argümanlarınız vb.) İçin kullanmanızı öneririm . Bu, kodunuzu daha genel hale getirir ve Listçok fazla kodu yeniden yazmak zorunda kalmadan gerektiğinde başka bir uygulamaya kolayca geçebilirsiniz .
Petr Pudlák

Bu iyi bir açıklama. Bu soruyu genişleten Arrays.asList () yöntemi de varargs alır. Belirli değerleri iletirsem, şunu yapıyorum: Arrays.asList (1,3,5) iki kez aynı Listeyi döndürür mü?
sbsatter

27

Bunun nedeni, ArrayListsonuç Arrays.asList()türünün olmamasıdır.java.util.ArrayList . genişlemeyen ancak yalnızca genişleyen Arrays.asList()bir ArrayListtür oluştururjava.util.Arrays$ArrayListjava.util.ArrayListjava.util.AbstractList


9
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy

Bu durumda, list1tiptedir ArrayList.

List<Integer> list2 = Arrays.asList(ia);

Burada liste bir Listgörünüm olarak döndürülür , yani sadece o arayüze eklenmiş yöntemlere sahiptir. Bu nedenle bazı yöntemlere izin verilmiyor list2.

ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));

Burada yeni bir yaratıyorsun ArrayList. Yapıcıya basitçe bir değer iletiyorsunuz. Bu bir döküm örneği değildir. Oyuncu seçerken daha çok şöyle görünebilir:

ArrayList list1 = (ArrayList)Arrays.asList(ia);

4

Burada oldukça geç kaldım, her neyse, doktor referansları içeren bir açıklamanın cevap arayan biri için daha iyi olacağını hissettim.

  1. java.util.Arrays
  • Bu, belirli bir dizide çalışmak için bir dizi statik yöntem içeren bir yardımcı sınıftır.
  • asList , girdi dizisini alan ve java.util.Arrays.ArrayList nesnesini döndüren böyle bir statik yöntemdir. List arayüzünü uygulayan AbstractList'i genişleten statik bir iç içe sınıf .
  • Yani Arrays.asList (inarray), giriş dizisi etrafında bir Liste sarıcısı döndürür, ancak bu sarmalayıcı java.util.ArrayList'dir ve java.util.ArrayList değildir ve aynı diziyi ifade eder, bu nedenle List sarılmış diziye daha fazla öğe eklemek etkileyecektir. orignal olanı da ve ayrıca uzunluğu değiştiremeyiz.
  1. java.util.ArrayList
  • ArrayList, aşırı yüklenmiş oluşturuculara sahiptir

    public ArrayList () - // varsayılan kapasitesi 10 olan dizi listesini döndürür

    public ArrayList (Koleksiyon c)

    public ArrayList (int initialCapacity)

  • Dolayısıyla, Arrays.asList döndürülen nesneyi, yani List (AbstractList) 'i yukarıdaki ikinci yapıcıya ilettiğimizde, yeni bir dinamik dizi oluşturacaktır (bu dizi boyutu, kapasitesinden daha fazla öğe ekledikçe artar ve ayrıca yeni öğeler, orijinal diziyi etkilemez. ) orijinal dizinin yüzeysel olarak kopyalanması ( sığ kopya , yalnızca referansların üzerine kopyalandığı ve orijinal dizideki ile aynı nesnelerin yeni bir kümesini oluşturmadığı anlamına gelir)


4
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> namesList = Arrays.asList(names);

veya

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> temp = Arrays.asList(names);         

Yukarıdaki İfade, sarmalayıcıyı giriş dizisine ekler. Bu nedenle, ekle ve kaldır gibi yöntemler, liste referans nesnesi 'namesList' için geçerli olmayacaktır.

Mevcut diziye / listeye bir öğe eklemeye çalışırsanız, "iş parçacığında Exception" main "java.lang.UnsupportedOperationException" alırsınız.

Yukarıdaki işlem salt okunur veya salt görüntülenebilir.
Liste nesnesine ekleme veya çıkarma işlemi yapamıyoruz. Fakat

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));

veya

String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> listObject = Arrays.asList(names);
java.util.ArrayList<String> list1 = new ArrayList<>(listObject);

Yukarıdaki ifadede, bir ArrayList sınıfının somut bir örneğini yarattınız ve bir listeyi parametre olarak ilettiniz.

Bu durumda, add & remove yöntemi, her iki yöntem de ArrayList sınıfından olduğu için düzgün çalışacaktır, bu nedenle burada herhangi bir UnSupportedOperationException almayacağız.
Arraylist nesnesinde yapılan değişiklikler (bir dizi listesine bir öğe ekleme veya bir dizi listesinden bir öğe çıkarma yöntemi) orijinal java.util.List nesnesine yansıtılmayacaktır.

String names[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};

java.util.List < String > listObject = Arrays.asList(names);
java.util.ArrayList < String > list1 = new ArrayList < > (listObject);
for (String string: list1) {
    System.out.print("   " + string);
}
list1.add("Alex"); //Added without any exception
list1.remove("Avinash"); //Added without any exception will not make any changes in original list in this case temp object.


for (String string: list1) {
    System.out.print("   " + string);
}
String existingNames[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};
java.util.List < String > namesList = Arrays.asList(names);
namesList.add("Bob"); // UnsupportedOperationException occur
namesList.remove("Avinash"); //UnsupportedOperationException

3

Öncelikle Arrays sınıfı, no içeren bir yardımcı program sınıfıdır. Arrays üzerinde çalışmak için yardımcı yöntem yöntemleri (Arrays sınıfı sayesinde, aksi takdirde Array nesneleri üzerinde hareket etmek için kendi yöntemlerimizi yaratmamız gerekirdi)

asList () yöntemi:

  1. asListyöntem, Arraysınıfın fayda yöntemlerinden biridir , statik yöntemdir, bu yüzden bu yöntemi sınıf adıyla çağırabiliriz (gibiArrays.asList(T...a) )
  2. Şimdi burada bükülme var, lütfen bu yöntemin yeni ArrayListnesne oluşturmadığını , sadece mevcut Arraynesneye bir Liste başvurusu döndürdüğünü unutmayın (bu nedenle asList, yöntemi kullandıktan sonra , mevcut nesneye iki referansArray nesneye oluşturulur)
  3. ve bu nedenle, Listnesne üzerinde çalışan tüm yöntemler bu Array nesnesi üzerinde List, örneğin,Array s boyutunun sabit olması nedenle Arraybu Listreferansı kullanarak nesneye öğe ekleyemez veya nesneden öğe kaldıramazsınız (gibi list.add(10)veyalist.remove(10); aksi takdirde UnsupportedOperationException oluşturur)
  4. liste referansını kullanarak yaptığınız herhangi bir değişiklik, çıkan Arraynesneye yansıtılacaktır (liste referansını kullanarak mevcut Array nesnesi üzerinde çalışırken)

İlk durumda, yeni bir Arraylistnesne oluşturuyorsunuz (2. durumda yalnızca mevcut Array nesnesine referans oluşturulur, ancak yeni bir ArrayListnesne değildir ), bu nedenle artık iki farklı nesne vardır; biri Arraynesne, diğeriArrayList nesne ve aralarında bağlantı yoktur (bu nedenle değişir bir nesnede başka bir nesneye yansıtılmayacak / etkilenmeyecektir (yani, 2. durumda Arrayve Arraylistiki farklı nesnedir)

dava 1:

Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  // new ArrayList object is created , no connection between existing Array Object
list1.add(5);
list1.add(6);
list1.remove(0);
list1.remove(0);
System.out.println("list1 : "+list1);
System.out.println("Array : "+Arrays.toString(ia));

durum 2:

Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list2 = Arrays.asList(ia); // creates only a (new ) List reference to existing Array object (and NOT a new ArrayList Object)
//  list2.add(5); //  it will throw java.lang.UnsupportedOperationException - invalid operation (as Array size is fixed)
list2.set(0,10);  // making changes in existing Array object using List reference - valid 
list2.set(1,11); 
ia[2]=12;     // making changes in existing Array object using Array reference - valid
System.out.println("list2 : "+list2);
System.out.println("Array : "+Arrays.toString(ia));

3

Pek çok insan mekanik detayları şimdiden cevapladı, ancak kayda değer: Bu Java tarafından yapılan kötü bir tasarım seçimi.

Java'nın asListyöntemi " Sabit boyutlu bir liste döndürür ..." olarak belgelenmiştir . Eğer sonucunu alır ve .addyöntemi çağırırsanız (söylerseniz), bir UnsupportedOperationException. Bu sezgisel olmayan bir davranıştır! Bir yöntem a döndürdüğünü söylüyorsa List, standart beklenti arabirim yöntemlerini destekleyen bir nesne döndürmesidir List. Bir geliştirici ezberlemek olmamalıdır hangi sayısız ait util.Listoluşturmak yöntemlerle Listaslında tüm desteklemeyen s Listyöntemleri.

Yöntemi adlandırmış asImmutableListolsalardı, mantıklı olurdu. Ya da yöntemin bir gerçek döndürmesini sağlasalar List(ve destek dizisini kopyalamışlarsa), bu mantıklı olacaktır. Bunlar çalışma zamanı-performans hem lehine karar verdi ve her iki ihlal pahasına, kısa adları İlke kaçınma Az Sürpriz ve iyi-OO uygulamaUnsupportedOperationException s.

(Ayrıca tasarımcılar interface ImmutableList, çok sayıda UnsupportedOperationExceptions'den kaçınmak için a yapmış olabilirler .)


2

Java 8'de yukarıdaki 'ia' tamsayı [] olmalı ve int [] olmamalıdır. Bir int dizisinin Arrays.asList () öğesi, tek öğeli bir liste döndürür. OP'nin kod parçacığını kullanırken, derleyici sorunu yakalar, ancak bazı yöntemler (örneğin, Collections.shuffle ()) beklediğiniz şeyi sessizce yapamaz.


1
ArrayList <Integer> al = new ArrayList <Integer> (Arrays.asList (a)) yaptığımda bu derleyici sorunuyla karşılaştım; a bir int [] idi. Benim al'mda da sadece tek bir öğe var, basıldığında çöp gibi görünüyordu. Bu unsur nedir? Ve oraya nasıl geliyor? Java 7'de bu sorunla karşılaştım
Jyotsana Nandwani

@JyotsanaNandwani Pls cevabımı kontrol et: stackoverflow.com/a/54105519/1163607
NINCOMPOOP

1
package com.copy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class CopyArray {

    public static void main(String[] args) {
        List<Integer> list1, list2 = null;
        Integer[] intarr = { 3, 4, 2, 1 };
        list1 = new ArrayList<Integer>(Arrays.asList(intarr));
        list1.add(30);
        list2 = Arrays.asList(intarr);
        // list2.add(40); Here, we can't modify the existing list,because it's a wrapper
        System.out.println("List1");
        Iterator<Integer> itr1 = list1.iterator();
        while (itr1.hasNext()) {
            System.out.println(itr1.next());
        }
        System.out.println("List2");
        Iterator<Integer> itr2 = list2.iterator();
        while (itr2.hasNext()) {
            System.out.println(itr2.next());
        }
    }
}

1

Arrays.asList()

bu yöntem kendi List uygulamasını döndürür. Bir diziyi argüman olarak alır ve üzerine yöntemler ve öznitelikler oluşturur, çünkü bir diziden herhangi bir veri kopyalamıyor, ancak orijinal diziyi kullanıyor bu, değiştirdiğinizde orijinal dizide değişikliğe neden oluyor Arrays.asList()yöntem tarafından döndürülen liste .

diğer yandan. argüman olarak bir listeyi alan ve ie'den bağımsız olan bir döndüren sınıf
ArrayList(Arrays.asList()); yapıcısıdır . bu durumda argüman olarak geçildi. bu yüzden bu sonuçları görüyorsunuz;ArrayListArrayListArrays.asList()


0
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

2. satırda, içinde tanımlanan iç sınıf nesnesinin Arrays.asList(ia)bir Listbaşvurusunu döndürür Arrays, bu da denir ArrayListancak özeldir ve yalnızca genişler AbstractList. Bu, geri dönen Arrays.asList(ia)şeyin, aldığınızdan farklı bir sınıf nesnesi olduğu anlamına gelir .new ArrayList<Integer> .

2. satırda bazı işlemleri kullanamazsınız çünkü içindeki özel sınıf Arrays bu yöntemleri sağlamaz.

Bu bağlantıya bir göz atın ve özel iç sınıfla neler yapabileceğinizi görün: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ Arrays.java # Arrays.ArrayList

Satır 1, ArrayList2. satırdan aldığınızdan öğeleri kopyalayan yeni bir nesne yaratır . Böylece java.util.ArrayList, tüm bu yöntemleri sağladığından, istediğinizi yapabilirsiniz .


0

Farkın özeti -

Liste yeni operatör Arrays.asList () yöntemi kullanılmadan oluşturulduğunda, Wrapper'ı döndürür, bu da

1. ekleme / güncelleme İşlemi gerçekleştirebilirsiniz.

2. Orijinal dizide yapılan değişiklikler Listeye de yansıtılacaktır ve tersi de geçerlidir.


0

Java 8'den beri Arrays.asList () işlevinin davranışı hakkında sorular soran bazı yorumlara yanıt olarak :

    int[] arr1 = {1,2,3};
    /* 
       Arrays are objects in Java, internally int[] will be represented by 
       an Integer Array object which when printed on console shall output
       a pattern such as 
       [I@address for 1-dim int array,
       [[I@address for 2-dim int array, 
       [[F@address for 2-dim float array etc. 
   */
    System.out.println(Arrays.asList(arr1)); 

    /* 
       The line below results in Compile time error as Arrays.asList(int[] array)
       returns List<int[]>. The returned list contains only one element 
       and that is the int[] {1,2,3} 
    */
    // List<Integer> list1 = Arrays.asList(arr1);

    /* 
       Arrays.asList(arr1) is  Arrays$ArrayList object whose only element is int[] array
       so the line below prints [[I@...], where [I@... is the array object.
    */
    System.out.println(Arrays.asList(arr1)); 

    /* 
     This prints [I@..., the actual array object stored as single element 
     in the Arrays$ArrayList object. 
    */
    System.out.println(Arrays.asList(arr1).get(0));

    // prints the contents of array [1,2,3]
    System.out.println(Arrays.toString(Arrays.asList(arr1).get(0)));

    Integer[] arr2 = {1,2,3};
    /* 
     Arrays.asList(arr) is  Arrays$ArrayList object which is 
     a wrapper list object containing three elements 1,2,3.
     Technically, it is pointing to the original Integer[] array 
    */
    List<Integer> list2 = Arrays.asList(arr2);

    // prints the contents of list [1,2,3]
    System.out.println(list2);
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.