एक लंबी सूची की एक सरणी को लोंगों की सूची में परिवर्तित करें


138

यह सवाल का एक आसान, हेडडेस्क प्रकार का हो सकता है, लेकिन मेरा पहला प्रयास आश्चर्यजनक रूप से काम करने में पूरी तरह से विफल रहा। मैं आदिम लोंगों की एक सरणी लेना चाहता था और इसे एक सूची में बदलना चाहता था, जिसे मैंने इस तरह से करने का प्रयास किया:

long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!

ऐसा करने का सही तरीका क्या है?


6
मुझे लगता है कि हम किलों के लिए एक ही सवाल है, हम नहीं?
टॉम हॉल्टिन -

जवाबों:


115

मैंने पाया यह सुविधाजनक Apache Commons का उपयोग कर ऐसा करने के लिए लैंग ArrayUtils ( JavaDoc , Maven निर्भरता )

import org.apache.commons.lang3.ArrayUtils;
...
long[] input = someAPI.getSomeLongs();
Long[] inputBoxed = ArrayUtils.toObject(input);
List<Long> inputAsList = Arrays.asList(inputBoxed);

इसका उल्टा एपीआई भी है

long[] backToPrimitive = ArrayUtils.toPrimitive(objectArray);

संपादित करें: टिप्पणियों और अन्य फ़िक्सेस द्वारा सुझाई गई सूची में पूर्ण रूपांतरण प्रदान करने के लिए अपडेट किया गया।


3
यह देखते हुए कि यह Longs का एक सरणी बनाता है , सूची नहीं , यह ओपी के सवाल का जवाब नहीं देता है और मेरा पतन हो जाता है। कैसे बिल्ली यह 56 upvotes और प्रतिष्ठित "जाँच" मिला ???
user949300

7
क्योंकि लोग आसानी से कर सकते हैं Arrays.asList(ArrayUtils.toObject(input))
एरन मेडन

मैं @ user949300 से सहमत हूं। इस सवाल का जवाब नहीं है।
dev4life

1
किसी सूची में पूर्ण रूपांतरण प्रदान करने के लिए इस उत्तर को अद्यतन किया जाना चाहिए। हालाँकि, यह समाधान की दिशा में एक कुशल कदम है।
जिम जेफर्स

2
@JimJeffers - धन्यवाद, पूर्ण रूपांतरण शामिल करने के लिए अपडेट किया गया। चूंकि ओपी ने List<Long> = Arrays.asList(inputBoxed)अपने प्रश्न में शामिल किया , इसलिए मैंने इसे दोहराने के लिए निरर्थक पाया क्योंकि मुझे लगा कि यह स्पष्ट था, मुझे लगता है कि मैं गलत था ...
एरन मेडन

114

Java 8 के बाद से अब आप इसके लिए स्ट्रीम का उपयोग कर सकते हैं:

long[] arr = {1,2,3,4};
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());

7
अच्छा है! दुर्भाग्य से, और कुछ रहस्यमय तरीके से, streamफ़ंक्शन केवल के लिए परिभाषित किया गया है int[], long[]और double[]
Norswap

1
वैकल्पिक रूप से, आप उपयोग कर सकते हैं LongStream.of(arr).boxed()...
एयरोबे

2
Arrays.stream(arr).boxed().collect(Collectors.toList());दुर्भाग्य से यह केवल लौट सकता हैList<Object>
सेंथिलकुमार अन्नादुराई

एक साधारण कार्य के लिए कोई भारी पुस्तकालय नहीं, कोई छोर नहीं। बहुत बढ़िया जवाब।
एलेक्स क्विलियम


35

हॉलिडेव और जेपलेसेक का सही विचार है- किसी सरणी पर चलना - लेकिन वे इसके द्वारा प्रदान की गई सुविधा का लाभ नहीं उठाते हैं ArrayList: चूँकि इस मामले में सूची का आकार ज्ञात है, आपको इसे बनाते समय निर्दिष्ट करना चाहिए ArrayList

List<Long> list = new ArrayList<Long>(input.length);
for (long n : input)
  list.add(n);

इस तरह, कोई अनावश्यक सरणियाँ केवल ArrayListइसलिए नहीं बनाई जाती हैं क्योंकि वे बहुत कम हो जाती हैं, और कोई खाली "स्लॉट" बर्बाद नहीं होता है क्योंकि ArrayListइसकी अंतरिक्ष आवश्यकताओं को कम करके आंका जाता है। बेशक, यदि आप सूची में तत्वों को जोड़ना जारी रखते हैं, तो एक नए बैकिंग सरणी की आवश्यकता होगी।


1
जब तक कोड किसी प्रदर्शन हॉट स्पॉट का हिस्सा साबित नहीं होता है या सरणी बहुत बड़ी होने की उम्मीद है तब तक मैं लंबाई विनिर्देश को छोड़ देता हूं। मुझे लगता है कि लंबाई छोड़ने से कोड थोड़ा अधिक पठनीय हो जाता है।
हॉलिडेव

19

थोड़ा और क्रिया, लेकिन यह काम करता है:

    List<Long> list = new ArrayList<Long>();
    for (long value : input) {
        list.add(value);
    }

आपके उदाहरण में यह प्रतीत होता है कि Arrays.asList () इनपुट की व्याख्या लॉन्ग की सूची के बजाय लंबी [] सरणियों की सूची के रूप में कर रहा है। थोड़ा आश्चर्य, यकीन के लिए। ऑटोबॉक्सिंग सिर्फ इस तरीके से काम नहीं करता जैसा आप इस मामले में करना चाहते हैं।


17

एक अन्य संभावना के रूप में, अमरुद पुस्तकालयLongs.asList() अन्य आदिम प्रकारों के लिए समान उपयोगिता वर्गों के साथ इसे प्रदान करता है ।

import com.google.common.primitives.Longs;

long[] input = someAPI.getSomeLongs();
List<Long> output = Longs.asList(input);

7

नहीं, आदिम प्रकार के सरणी से उनके बॉक्सिंग संदर्भ प्रकारों के सरणी में कोई स्वचालित रूपांतरण नहीं है। आप ही कर सकते हैं

long[] input = someAPI.getSomeLongs();
List<Long> lst = new ArrayList<Long>();

for(long l : input) lst.add(l);

7

किसी एरे को सूची में कैसे बदला जाए, इस बारे में सवाल पूछा गया। अब तक के अधिकांश जवाबों ने दिखाया कि कैसे सरणी के समान सामग्री के साथ एक नई सूची बनाई जाए या तीसरे पक्ष के पुस्तकालयों को संदर्भित किया जाए। हालांकि, इस प्रकार के रूपांतरण के लिए सरल, अंतर्निहित विकल्प हैं। उनमें से कुछ पहले से ही अन्य उत्तरों (जैसे यह एक ) में स्केच किए गए हैं । लेकिन मैं यहां लागू करने के लिए कुछ हद तक स्वतंत्रता की ओर इशारा करना चाहता हूं, और संभावित लाभ, कमियां और कैविएट दिखाना चाहता हूं।

बनाने के लिए कम से कम दो महत्वपूर्ण भेद हैं:

  • चाहे जिसके परिणामस्वरूप सूची एक होना चाहिए देखने वालों पर या क्या यह एक होना चाहिए नई सूची
  • परिणामी सूची संशोधित होनी चाहिए या नहीं

यहां विकल्पों को जल्दी से सारांशित किया जाएगा, और इस जवाब के निचले भाग में एक पूरा उदाहरण कार्यक्रम दिखाया गया है।


सरणी पर एक दृश्य बनाने बनाम एक नई सूची बनाना

जब परिणाम एक नई सूची होनी चाहिए , तो अन्य उत्तरों में से एक दृष्टिकोण का उपयोग किया जा सकता है:

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

6

जावा 8 के साथ एक और तरीका।

long[] input = someAPI.getSomeLongs();
LongStream.of(input).boxed().collect(Collectors.toList()));

6

मैं इन समस्याओं के लिए एक छोटी सी लाइब्रेरी लिख रहा हूँ:

long[] input = someAPI.getSomeLongs();
List<Long> = $(input).toList();

मामले में आप इसे यहाँ जाँचें ।


अच्छा पुस्तकालय! सबसे पहले, मुझे यकीन नहीं था कि यह जावा था ... मुझे JQuery की शैली पसंद है
यानिक रोचॉन

4

जावा 8 के साथ एक और तरीका

final long[] a = new long[]{1L, 2L};
final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.toList());

1
सूची वापस करते समय (इसे असाइन नहीं करना), मैंने पाया कि मुझे क्या करना है:Arrays.stream(a).boxed().collect(Collectors.<Long>toList());
जॉन


3

पावेल और टॉम के उत्तरों को मिलाकर हमें यह मिलता है

   @SuppressWarnings("unchecked")
    public static <T> List<T> asList(final Object array) {
        if (!array.getClass().isArray())
            throw new IllegalArgumentException("Not an array");
        return new AbstractList<T>() {
            @Override
            public T get(int index) {
                return (T) Array.get(array, index);
            }

            @Override
            public int size() {
                return Array.getLength(array);
            }
        };
    }

2

यदि आप भी ऐसा ही शब्दार्थ चाहते हैं, Arrays.asListतो आपको List(शायद किसी और के) ग्राहक कार्यान्वयन को लिखना (या उपयोग करना होगा) (शायद इसके माध्यम से AbstractListही लागू होना चाहिए) Arrays.asList, केवल बॉक्स और अनबॉक्स मान।


2

आप ट्रांस्मॉर्फ का उपयोग कर सकते हैं :

Transmorph transmorph = new Transmorph(new DefaultConverters());
List<Long> = transmorph.convert(new long[] {1,2,3,4}, new TypeReference<List<Long>>() {});

यह भी काम करता है अगर स्रोत उदाहरण के लिए ints की एक सरणी है।


2

मुझे पता है कि यह सवाल काफी पुराना है, लेकिन ... आप अपनी खुद की रूपांतरण विधि भी लिख सकते हैं:

@SuppressWarnings("unchecked")
public static <T> List<T> toList(Object... items) {

    List<T> list = new ArrayList<T>();

    if (items.length == 1 && items[0].getClass().isArray()) {
        int length = Array.getLength(items[0]);
        for (int i = 0; i < length; i++) {
            Object element = Array.get(items[0], i);
            T item = (T)element;
            list.add(item);
        }
    } else {
        for (Object i : items) {
            T item = (T)i;
            list.add(item);
        }
    }

    return list;
}

आपके द्वारा स्थैतिक आयात का उपयोग करने के बाद, संभावित उपयोग हो सकते हैं:

    long[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    List<Long> list = toList(array);

या

    List<Long> list = toList(1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l);

2
के बारे में: catch (ArrayIndexOutOfBoundsException ex) { /* Finished getting array elements */ }आप एक भयानक व्यक्ति हैं।
ब्रैंडन यारब्रॉट

अरे, यार, इसके लिए धन्यवाद! आपकी विडंबनापूर्ण टिप्पणी ने मुझे एक बेहतर समाधान दिया - सरणी की लंबाई Array.getLength () के माध्यम से प्राप्त करना।
पावल नेटेसा

1
बहुत खुबस! मुझे ख़ुशी है कि मेरे व्यंग्यात्मक रवैये के कारण चारों ओर केवल सामान्य बुरी भावनाओं के बजाय प्रगति हुई :) वास्तव में, बहुत ही असामान्य स्थितियों को छोड़कर अपवादों का उपयोग करना अच्छा नहीं है। वे बनाने के लिए आश्चर्यजनक रूप से महंगे हैं। यह नया संस्करण ज्यादा है, बहुत तेजी से।
ब्रैंडन यारब्रॉट

1

हालांकि एक नई सूची बनाना और उसमें सभी मूल्यों को जोड़ना (लूप या धाराओं के माध्यम से) संभव है, मैं वास्तव में बड़ी सरणियों पर काम कर रहा हूं और खराब प्रदर्शन प्राप्त कर रहा हूं। इसलिए मैंने आदिम सरणी आवरण वर्ग का उपयोग करने के लिए अपना आसान बनाया।

उदाहरण:

long[] arr = new long[] {1,2,3};
PrimativeList<Long> list = PrimativeList.create(arr); // detects long[] and returns PrimativeList<Long>

System.out.println(list.get(1)); // prints: 2
list.set(2, 15);
System.out.println(arr[2]);  // prints: 15

इसे यहां प्राप्त करें: https://github.com/Sf298/Sauds-Toolbox/blob/master/src/main/java/PrimitiveArrayWrapper/PrimitiveList.java

नोट: मैंने अभी तक इसका पूरी तरह से परीक्षण नहीं किया है, इसलिए मुझे बताएं कि क्या आपको कोई बग / समस्या मिलती है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.