আদিম আকাঙ্ক্ষার একটি অ্যারেটিকে লংসের তালিকায় রূপান্তর করুন


138

এটি একটি সহজ, শিরোনামহীন ধরণের প্রশ্ন হতে পারে, কিন্তু আমার প্রথম প্রচেষ্টা আশ্চর্যজনকভাবে কাজ করতে ব্যর্থ হয়েছে। আমি আদিম আকাঙ্ক্ষার অ্যারে নিতে এবং এটিকে একটি তালিকায় পরিণত করতে চেয়েছিলাম, যা আমি এরকম করার চেষ্টা করেছি:

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

এটি করার সঠিক উপায় কী?


6
আমি মনে করি আমাদের কাছে একই প্রশ্নগুলি ইন্টের জন্য ছিল, তাই না?
টম হাটিন -

উত্তর:


115

আমি দেখেছি সুবিধামতো Apache কমন্স ব্যবহার করতে ল্যাঙ ArrayUtils ( JavaDoc , ম্যাভেন নির্ভরতা )

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
বিবেচনা করে যে এটি কোনও তালিকার চেয়ে লংসের অ্যারে তৈরি করে , এটি ওপির প্রশ্নের উত্তর দেয় না এবং আমার ডাউনওয়েট পায়। কীভাবে হ্যাক এই 56 টি উপস্থাপনা এবং লোভিত "চেক" পেয়েছে ???
user949300

7
কারণ মানুষ সহজেই করতে পারে Arrays.asList(ArrayUtils.toObject(input))
ইরান মেডান

আমি @ user949300 এর সাথে একমত এটি প্রশ্নের উত্তর দেয় না।
dev4Live

1
এই উত্তরটি তালিকায় সম্পূর্ণ রূপান্তর করতে আপডেট করা উচিত। তবে এটি সমাধানের দিকে কার্যকর পদক্ষেপ।
জিম জেফার্স

2
@ জিমজেফার্স - ধন্যবাদ, সম্পূর্ণ রূপান্তর অন্তর্ভুক্ত করার জন্য আপডেট হয়েছে। যেহেতু ওপি List<Long> = Arrays.asList(inputBoxed)তাদের প্রশ্নের মধ্যে অন্তর্ভুক্ত করেছে আমি এটি পুনরুক্ত করা অপ্রয়োজনীয় বলে মনে করেছি যেহেতু আমি এটিকে স্পষ্ট বলে মনে করেছি, আমি অনুমান করি যে আমি ভুল ছিল ...
ইরান মেডান

114

জাভা 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

হলিডেভ এবং জপালেসেকের সঠিক ধারণা রয়েছে an একটি অ্যারের উপরে পুনরাবৃত্তি — তবে তারা প্রদত্ত কোনও বৈশিষ্ট্যের সদ্ব্যবহার করেন না ArrayList: যেহেতু তালিকার আকারটি এই ক্ষেত্রে পরিচিত , তাই আপনি এটি তৈরি করার সময় এটি নির্দিষ্ট করতে হবে ArrayList

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

এইভাবে, কোনও অপ্রয়োজনীয় অ্যারে কেবল তা ফেলে দেওয়ার জন্য তৈরি করা হয়নি ArrayListকারণ এগুলি খুব সংক্ষিপ্ত আকারে পরিণত হয় এবং কোনও ফাঁকা "স্লট" নষ্ট হয় না কারণ ArrayListএর জায়গার প্রয়োজনীয়তা অতিরঞ্জিত করে। অবশ্যই, আপনি যদি তালিকায় উপাদান যুক্ত করতে থাকেন তবে একটি নতুন ব্যাকিং অ্যারের প্রয়োজন হবে।


1
কোডটি যদি কোনও পারফরম্যান্স হট স্পটের অংশ হিসাবে প্রমাণিত না হয় বা অ্যারে অত্যন্ত বড় বলে আশা করা হয় তবে আমি দৈর্ঘ্যের স্পেসিফিকেশনটি ছাড়ব leave আমি মনে করি দৈর্ঘ্য ছাড়াই কোডটি কিছুটা বেশি পঠনযোগ্য।
হলিডেভ

19

কিছুটা আরও ভার্বোজ, তবে এটি কাজ করে:

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

আপনার উদাহরণে এটি উপস্থিত হয় যে অ্যারে.এএসলিস্ট () লংসের তালিকার পরিবর্তে দীর্ঘ [] অ্যারের তালিকা হিসাবে ইনপুটটি ব্যাখ্যা করছে। কিছুটা অবাক করার বিষয় অবশ্যই। অটোবক্সিং এক্ষেত্রে আপনি যেভাবে চান তা ঠিক তেমন কাজ করে না।



7

না, আদিম ধরণের অ্যারে থেকে তাদের বক্সযুক্ত রেফারেন্স ধরণের অ্যারেতে কোনও স্বয়ংক্রিয় রূপান্তর নেই। আপনি শুধুমাত্র করতে পারেন

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

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

7

অ্যারেটিকে কীভাবে তালিকায় পরিণত করবেন সে সম্পর্কে প্রশ্ন জিজ্ঞাসা করা হয়েছিল। এখনও অবধি বেশিরভাগ উত্তর দেখিয়েছে কীভাবে অ্যারে হিসাবে একই বিষয়বস্তু সহ একটি নতুন তালিকা তৈরি করা যায়, বা তৃতীয় পক্ষের লাইব্রেরিগুলিতে উল্লেখ করা হয়। তবে এই ধরণের রূপান্তরটির জন্য সহজ, অন্তর্নির্মিত বিকল্প রয়েছে। এর মধ্যে কয়েকটি ইতিমধ্যে অন্যান্য উত্তরে স্কেচ করা হয়েছে (যেমন এটি ) this তবে আমি এখানে বাস্তবায়নের জন্য স্বাধীনতার কয়েকটি ডিগ্রি তুলে ধরতে এবং বিস্তারিত জানাতে চাই এবং সম্ভাব্য সুবিধাগুলি, ঘাটতি এবং সতর্কতাগুলি প্রদর্শন করতে চাই।

কমপক্ষে দুটি গুরুত্বপূর্ণ পার্থক্য করতে হবে:

  • ফলাফলের তালিকাটি অ্যারেতে একটি ভিউ হওয়া উচিত বা এটি একটি নতুন তালিকা হওয়া উচিত
  • কিনা ফলে তালিকা থাকা উচিত সংশোধনযোগ্য বা না

বিকল্পগুলি এখানে দ্রুত সংক্ষিপ্ত করা হবে এবং এই উত্তরের নীচে একটি সম্পূর্ণ উদাহরণ প্রোগ্রাম দেখানো হবে।


অ্যারেতে একটি ভিউ তৈরি করা বনাম একটি নতুন তালিকা তৈরি করা

যখন ফলাফলটি একটি নতুন তালিকা হওয়া উচিত , তখন অন্য উত্তরগুলির একটি পদ্ধতির ব্যবহার করা যেতে পারে:

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?

পরিবর্তনযোগ্য যে অ্যারেতে একটি তালিকা ভিউ তৈরি করা সম্ভব । এর অর্থ এই যে তালিকাতে পরিবর্তনগুলি যেমন একটি নির্দিষ্ট সূচকে নতুন মান নির্ধারণের মতো অ্যারেতে দৃশ্যমান হবে।

তবে কাঠামোগতভাবে সংশোধনযোগ্য এমন একটি তালিকা ভিউ তৈরি করা সম্ভব নয় । এর মানে হল যে তালিকার আকারকে প্রভাবিত করে এমন ক্রিয়াকলাপ করা সম্ভব নয় । এটি কেবল কারণ অন্তর্নিহিত অ্যারের আকার পরিবর্তন করা যায় না।


নীচে একটি এমসিভিই রয়েছে যা বিভিন্ন প্রয়োগের বিকল্পগুলি এবং ফলাফলের তালিকাটি ব্যবহারের সম্ভাব্য উপায়গুলি দেখায়:

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();

ক্ষেত্রে আপনি যত্ন এখানে এটি পরীক্ষা করুন


চমৎকার গ্রন্থাগার! প্রথমে, আমি নিশ্চিত নই যে এটি জাভা ছিল ... আমি জিকুয়েরি স্টাইল পছন্দ করি
ইয়ানিক রোচন

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 */ }:, আপনি একটি ভয়ঙ্কর ব্যক্তি।
ব্র্যান্ডন ইয়ারব্রু

আরে মানুষ, তার জন্য ধন্যবাদ! আপনার বিদ্রূপাত্মক মন্তব্যটি আমাকে আরও ভাল সমাধান সন্ধান করতে বাধ্য করেছে - অ্যারে.জেটলেন্থ () এর মাধ্যমে অ্যারের দৈর্ঘ্য পেয়ে।
পাভেল নীতাসা

1
ফ্যান্টাস্টিক! আমি আনন্দিত যে আমার চর্চা আচরণটি চারদিকে কেবল সাধারণ খারাপ অনুভূতির পরিবর্তে অগ্রগতির দিকে পরিচালিত করেছিল :) সত্যিই, খুব অস্বাভাবিক পরিস্থিতি ব্যতীত ব্যতিক্রমগুলি ব্যবহার করা ভাল ধারণা নয়। এগুলি তৈরি করা আশ্চর্যরকম ব্যয়বহুল। এই নতুন সংস্করণটি অনেক বেশি দ্রুত faster
ব্র্যান্ডন ইয়ারব্রু

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

দ্রষ্টব্য: আমি এখনও এটি পুরোপুরি পরীক্ষা করে দেখিনি, সুতরাং আপনি যদি কোনও বাগ / সমস্যা খুঁজে পান তবে আমাকে জানান।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.