किसी एरे को सूची में कैसे बदला जाए, इस बारे में सवाल पूछा गया। अब तक के अधिकांश जवाबों ने दिखाया कि कैसे सरणी के समान सामग्री के साथ एक नई सूची बनाई जाए या तीसरे पक्ष के पुस्तकालयों को संदर्भित किया जाए। हालांकि, इस प्रकार के रूपांतरण के लिए सरल, अंतर्निहित विकल्प हैं। उनमें से कुछ पहले से ही अन्य उत्तरों (जैसे यह एक ) में स्केच किए गए हैं । लेकिन मैं यहां लागू करने के लिए कुछ हद तक स्वतंत्रता की ओर इशारा करना चाहता हूं, और संभावित लाभ, कमियां और कैविएट दिखाना चाहता हूं।
बनाने के लिए कम से कम दो महत्वपूर्ण भेद हैं:
- चाहे जिसके परिणामस्वरूप सूची एक होना चाहिए देखने वालों पर या क्या यह एक होना चाहिए नई सूची
- परिणामी सूची संशोधित होनी चाहिए या नहीं
यहां विकल्पों को जल्दी से सारांशित किया जाएगा, और इस जवाब के निचले भाग में एक पूरा उदाहरण कार्यक्रम दिखाया गया है।
सरणी पर एक दृश्य बनाने बनाम एक नई सूची बनाना
जब परिणाम एक नई सूची होनी चाहिए , तो अन्य उत्तरों में से एक दृष्टिकोण का उपयोग किया जा सकता है:
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
लेकिन किसी को ऐसा करने की कमियों पर विचार करना चाहिए: 1000000 long
मूल्यों वाला एक सरणी लगभग 8 मेगाबाइट मेमोरी पर कब्जा कर लेगा। नई सूची भी लगभग 8 मेगाबाइट पर कब्जा कर लेगी । और निश्चित रूप से, इस सूची को बनाते समय पूर्ण सरणी का पता लगाया जाना चाहिए। कई मामलों में, एक नई सूची बनाना बस आवश्यक नहीं है। इसके बजाय, यह सरणी पर एक दृश्य बनाने के लिए पर्याप्त है :
// 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
विधि के कार्यान्वयन के लिए नीचे दिए गए उदाहरण देखें )
सरणी पर एक दृश्य होने का निहितार्थ यह है कि सरणी में परिवर्तन सूची में दिखाई देंगे:
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!
सौभाग्य से, एक प्रतिलिपि बनाना (यानी, एक नई सूची जो व्यू में संशोधन से प्रभावित नहीं होती) दृश्य से तुच्छ है:
List<Long> copy = new ArrayList<Long>(asList(array));
अब, यह एक सच्ची प्रतिलिपि है, जो स्ट्रीम-आधारित समाधान के साथ प्राप्त की गई है, जो कि ऊपर दिखाया गया था।
एक परिवर्तनीय दृश्य या एक अपरिवर्तनीय दृश्य बनाना
कई मामलों में, यह पर्याप्त होगा जब सूची केवल पढ़ने के लिए होगी । परिणामी सूची की सामग्री को अक्सर संशोधित नहीं किया जाएगा, लेकिन केवल डाउनस्ट्रीम प्रसंस्करण के लिए पारित किया गया है जो केवल सूची को पढ़ता है।
सूची में संशोधन की अनुमति देने से कुछ सवाल उठते हैं:
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?
यह उस सरणी पर एक सूची दृश्य बनाना संभव है जो कि परिवर्तनीय है । इसका मतलब यह है कि सूची में परिवर्तन, एक निश्चित सूचकांक पर एक नया मान सेट करने की तरह, सरणी में दिखाई देगा।
लेकिन एक सूची दृश्य बनाना संभव नहीं है जो संरचनात्मक रूप से परिवर्तनीय है । इसका मतलब यह है कि ऑपरेशन करना संभव नहीं है जो सूची के आकार को प्रभावित करता है । यह केवल इसलिए है क्योंकि अंतर्निहित सरणी का आकार परिवर्तित नहीं किया जा सकता है।
निम्नलिखित कार्यान्वयन विकल्पों को दिखाने वाला एक MCVE है , और परिणामी सूचियों का उपयोग करने के संभावित तरीके:
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();
}
}
उदाहरण का आउटपुट यहाँ दिखाया गया है:
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