Soru, bir dizinin listeye nasıl dönüştürüleceğini sordu. Şimdiye kadar cevapların çoğu , diziyle aynı içeriğe sahip yeni bir listenin nasıl oluşturulacağını veya üçüncü taraf kitaplıklarına atıfta bulunulduğunu gösterdi. Ancak, bu tür bir dönüşüm için basit, yerleşik seçenekler vardır. Bazıları zaten (diğer yanıtlar örneğin kabataslak edilmiş bu bir ). Ancak, burada uygulama için belirli derecede serbestlik konularına dikkat çekmek ve potansiyel faydaları, dezavantajları ve uyarıları göstermek istiyorum.
Yapılacak en az iki önemli ayrım vardır:
- Sonuçta elde edilen listenin dizi üzerinde bir görünüm olup olmadığı veya yeni bir liste olup olmadığı
- Ortaya çıkan liste olmalıdır olsun değiştirilebilir veya olmasın
Seçenekler burada hızlı bir şekilde özetlenecek ve bu cevabın altında tam bir örnek program gösterilecektir.
Dizide görünüm oluşturmaya karşı yeni bir liste oluşturma
Sonuç yeni bir liste olduğunda, diğer cevaplardan yaklaşımlardan biri kullanılabilir:
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
Ancak bunu yapmanın dezavantajları düşünülmelidir: 1000000 long
değerine sahip bir dizi kabaca 8 Megabayt bellek kaplayacaktır. Yeni liste ayrıca yaklaşık 8 Megabayt kaplayacak. Ve elbette, bu liste oluşturulurken tam dizi geçilmelidir. Çoğu durumda, yeni bir liste oluşturmak gerekli değildir. Bunun yerine, dizide bir görünüm oluşturmak yeterlidir :
// This occupies ca. 8 MB
long array[] = { /* 1 million elements */ }
// Properly implemented, this list will only occupy a few bytes,
// and the array does NOT have to be traversed, meaning that this
// operation has nearly ZERO memory- and processing overhead:
List<Long> list = asList(array);
( toList
Yöntemin uygulanması için alttaki örneğe bakın )
Dizide bir görünüme sahip olmanın anlamı , dizideki değişikliklerin listede görünür olmasıdır:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
System.out.println(list.get(1)); // This will print 34
// Modify the array contents:
array[1] = 12345;
System.out.println(list.get(1)); // This will now print 12345!
Neyse ki, görünümden bir kopya (yani, dizideki değişikliklerden etkilenmeyen yeni bir liste) oluşturmak önemsizdir:
List<Long> copy = new ArrayList<Long>(asList(array));
Şimdi, bu, yukarıda gösterilen akış tabanlı çözümle elde edilene eşdeğer gerçek bir kopyadır.
Bir oluşturma değiştirilebilir bir görünüm veya değiştirilemeyen bir görünüm
Çoğu durumda, liste salt okunur olduğunda yeterli olacaktır . Ortaya çıkan listenin içeriği genellikle değiştirilmez, yalnızca listeyi okuyan aşağı akış işlemine geçirilir.
Listede değişiklik yapılmasına izin verilmesi bazı sorulara neden olur:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
list.set(2, 34567); // Should this be possible?
System.out.println(array[2]); // Should this print 34567?
list.set(3, null); // What should happen here?
list.add(99999); // Should this be possible?
Dizide değiştirilebilir bir liste görünümü oluşturmak mümkündür . Bu, listedeki belirli bir dizinde yeni bir değer ayarlamak gibi değişikliklerin dizide görüneceği anlamına gelir.
Ancak yapısal olarak değiştirilebilen bir liste görünümü oluşturmak mümkün değildir . Bu , listenin boyutunu etkileyen işlemlerin yapılamayacağı anlamına gelir . Bunun nedeni temeldeki dizinin boyutunun değiştirilememesidir.
Aşağıda, farklı uygulama seçeneklerini ve sonuçta ortaya çıkan listeleri kullanmanın olası yollarını gösteren bir MCVE yer almaktadır:
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.RandomAccess;
public class PrimitiveArraysAsLists
{
public static void main(String[] args)
{
long array[] = { 12, 34, 56, 78 };
// Create VIEWS on the given array
List<Long> list = asList(array);
List<Long> unmodifiableList = asUnmodifiableList(array);
// If a NEW list is desired (and not a VIEW on the array), this
// can be created as well:
List<Long> copy = new ArrayList<Long>(asList(array));
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
// Modify a value in the array. The changes will be visible
// in the list and the unmodifiable list, but not in
// the copy.
System.out.println("Changing value at index 1 of the array...");
array[1] = 34567;
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
// Modify a value of the list. The changes will be visible
// in the array and the unmodifiable list, but not in
// the copy.
System.out.println("Changing value at index 2 of the list...");
list.set(2, 56789L);
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
// Certain operations are not supported:
try
{
// Throws an UnsupportedOperationException: This list is
// unmodifiable, because the "set" method is not implemented
unmodifiableList.set(2, 23456L);
}
catch (UnsupportedOperationException e)
{
System.out.println("Expected: " + e);
}
try
{
// Throws an UnsupportedOperationException: The size of the
// backing array cannot be changed
list.add(90L);
}
catch (UnsupportedOperationException e)
{
System.out.println("Expected: " + e);
}
try
{
// Throws a NullPointerException: The value 'null' cannot be
// converted to a primitive 'long' value for the underlying array
list.set(2, null);
}
catch (NullPointerException e)
{
System.out.println("Expected: " + e);
}
}
/**
* Returns an unmodifiable view on the given array, as a list.
* Changes in the given array will be visible in the returned
* list.
*
* @param array The array
* @return The list view
*/
private static List<Long> asUnmodifiableList(long array[])
{
Objects.requireNonNull(array);
class ResultList extends AbstractList<Long> implements RandomAccess
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public int size()
{
return array.length;
}
};
return new ResultList();
}
/**
* Returns a view on the given array, as a list. Changes in the given
* array will be visible in the returned list, and vice versa. The
* list does not allow for <i>structural modifications</i>, meaning
* that it is not possible to change the size of the list.
*
* @param array The array
* @return The list view
*/
private static List<Long> asList(long array[])
{
Objects.requireNonNull(array);
class ResultList extends AbstractList<Long> implements RandomAccess
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public Long set(int index, Long element)
{
long old = array[index];
array[index] = element;
return old;
}
@Override
public int size()
{
return array.length;
}
};
return new ResultList();
}
}
Örneğin çıktısı burada gösterilmiştir:
array : [12, 34, 56, 78]
list : [12, 34, 56, 78]
unmodifiableList: [12, 34, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 1 of the array...
array : [12, 34567, 56, 78]
list : [12, 34567, 56, 78]
unmodifiableList: [12, 34567, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 2 of the list...
array : [12, 34567, 56789, 78]
list : [12, 34567, 56789, 78]
unmodifiableList: [12, 34567, 56789, 78]
copy : [12, 34, 56, 78]
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.NullPointerException