জাভাতে অপরিহার্য অ্যারে


158

জাভাতে আদিম অ্যারেগুলির কোন অপরিবর্তনীয় বিকল্প আছে? আদিম অ্যারে করা finalআসলে কাউকে এরকম কিছু করতে বাধা দেয় না

final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;

আমি চাই অ্যারের উপাদানগুলি অপরিবর্তনীয় হয়।


43
আপনার পক্ষে একটি উপকার করুন এবং জাভাতে অ্যারেগুলি ব্যবহারের জন্য 1) ছাড়াও যেকোনটির জন্য বন্ধ করুন) 2) ভারী সংখ্যা ক্রাঞ্চিং 3) আপনার নিজের তালিকা / সংগ্রহ বাস্তবায়নের প্রয়োজন হলে (যা বিরল )। এগুলি অত্যন্ত জটিল এবং পুরানো ... যেমন আপনি এই প্রশ্নের সাথে সবেমাত্র আবিষ্কার করেছেন।
তিমি

39
@ হুইল, এবং পারফরম্যান্স এবং কোড যেখানে আপনার "গতিশীল" অ্যারে দরকার নেই। অ্যারেগুলি এখনও প্রচুর জায়গায় কার্যকর, এটি খুব বিরল নয়।
কলিন হেবার্ট

10
@ কলিন: হ্যাঁ তবে তারা কঠোরভাবে বাধা দিচ্ছেন; "আমার কি সত্যিই এখানে অ্যারে লাগবে বা আমি পরিবর্তে একটি তালিকা ব্যবহার করতে পারি?"
জেসন এস

7
@ কলিন: আপনার যখন প্রয়োজন তখনই অনুকূলিত হন। আপনি যখন নিজেকে অর্ধ মিনিট ব্যয় করে এমন কোনও কিছু যুক্ত করতে দেখেন যা উদাহরণস্বরূপ, একটি অ্যারের বড় করে দেয় বা আপনি কোনও সূচককে ফর লুপের আওতার বাইরে রাখেন, আপনি ইতিমধ্যে আপনার বসের কিছু সময় নষ্ট করেছেন। প্রথমে তৈরি করুন, কখন এবং কোথায় এটি প্রয়োজন - এবং সবচেয়ে বেশি অ্যাপ্লিকেশনগুলিতে, তালিকাটি অ্যারেগুলিতে প্রতিস্থাপনের ক্ষেত্রে নয় optim
fwielstra

9
ওয়েল, কেন কেউ কিছু উল্লেখ int[]এবং new int[]তুলনায় টাইপ করতে সহজ হয় List<Integer>এবং new ArrayList<Integer>? এক্সডি
lcn

উত্তর:


164

আদিম অ্যারে দিয়ে নয়। আপনাকে একটি তালিকা বা অন্য কোনও ডেটা কাঠামো ব্যবহার করতে হবে:

List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));

18
কোনওভাবেই আমি আরে.এএসলিস্ট (টি ...) সম্পর্কে কখনই জানতাম না। আমার ধারণা আমি এখনই আমার ListUtils.list (টি ...) থেকে মুক্তি পেতে পারি।
ম্যাটআরএস

3
যাইহোক, অ্যারেএস.এললিস্ট একটি
অবিচ্ছেদ্য

3
@ টনি যে অ্যারেলিস্ট জাভা ইউটিলের নয়
মউহিজ

11
@mauhiz Arrays.asListহয় না unmodifiable। docs.oracle.com/javase/7/docs/api/java/util/... "(" অ্যারে হতে। মাধ্যমে লেখ ফিরে লিস্টে পরিবর্তনসমূহ) "রিটার্নস একটি নির্দিষ্ট আকার তালিকা নির্দিষ্ট বিন্যাস সমর্থন।"
জেসন এস

7
@JasonS ভাল, Arrays.asList()প্রকৃতপক্ষে বলে মনে হয় অর্থে unmodifiable যে তুমি পারবে না addবা removeএর ফিরে আইটেম java.util.Arrays.ArrayList( বিভ্রান্ত করা যাবে না দিয়ে java.util.ArrayList) - এই ক্রিয়াকলাপগুলি শুধু বাস্তবায়িত হয় না। হয়তো @ মমহিজ এটি বলার চেষ্টা করে? তবে অবশ্যই আপনি বিদ্যমান উপাদানগুলির সাথে পরিবর্তন করতে পারেন List<> aslist = Arrays.asList(...); aslist.set(index, element), সুতরাং java.util.Arrays.ArrayListঅবশ্যই আপত্তিযোগ্য নয়, কিউইডি কেবল ফলাফল asListএবং স্বাভাবিকের মধ্যে পার্থক্যের উপর জোর দেওয়ার জন্য মন্তব্যটি যুক্ত করেছেনArrayList
এনআইএ

73

আমার সুপারিশ একটি অ্যারের অথবা একটি ব্যবহার করবেন হয় unmodifiableListকিন্তু ব্যবহার করতে পেয়ারা এর ImmutableList , যা এই উদ্দেশ্যে বিদ্যমান।

ImmutableList<Integer> values = ImmutableList.of(0, 1, 2, 3);

3
+1 পেয়ারার ইমমিটেবললিস্ট কালেকশন.অনোমডিফাইয়েবললিস্টের চেয়ে আরও ভাল, কারণ এটি একটি পৃথক প্রকার।
সেলসেকে

29
অপরিবর্তনীয় কারণ ইমিটেবললিস্ট প্রায়শই ভাল (এটি ব্যবহারের ক্ষেত্রে নির্ভর করে)। সংগ্রহ.আমিনোডিফাইয়েবললিস্টটি পরিবর্তনযোগ্য নয়। বরং এটি এমন একটি দৃষ্টিভঙ্গি যা প্রাপকরা পরিবর্তন করতে পারবেন না, তবে আসল উত্সটি পরিবর্তন করতে পারে।
চার্লি কলিন্স

2
@ চর্লিকোলিনস, যদি কোনও Collections.unmodifiableListতালিকা অপরিবর্তনীয় পর্যাপ্ত করার চেয়ে পর্যায়ে আসল উত্স অ্যাক্সেস করার উপায় না থাকে ?
সাভনিভারত

1
@ সাবানভরত হ্যাঁ
ঠিক

20

অন্যরা যেমন উল্লেখ করেছে, আপনার জাভাতে পরিবর্তনযোগ্য অ্যারে থাকতে পারে না।

যদি আপনার একেবারে এমন কোনও পদ্ধতির প্রয়োজন হয় যা এমন অ্যারে ফেরত দেয় যা আসল অ্যারেটিকে প্রভাবিত করে না, তবে আপনাকে প্রতিবার অ্যারে ক্লোন করতে হবে:

public int[] getFooArray() {
  return fooArray == null ? null : fooArray.clone();
}

স্পষ্টতই এটি ব্যয়বহুল (যেমন আপনি প্রতিবার প্রত্যক্ষকারকে কল করার সময় একটি সম্পূর্ণ অনুলিপি তৈরি করবেন) তবে আপনি যদি ইন্টারফেসটি পরিবর্তন করতে না পারেন ( Listউদাহরণস্বরূপ ব্যবহার করতে) এবং ক্লায়েন্টকে আপনার অভ্যন্তরগুলি পরিবর্তন করতে পারে না, এটি প্রয়োজন হতে পারে।

এই কৌশলটি একটি প্রতিরক্ষামূলক অনুলিপি তৈরি বলা হয়।


3
কোথায় তিনি উল্লেখ করেছিলেন যে তার একজন প্রযোজকের দরকার ছিল?
এরিক রবার্টসন

6
@ এরিক: তিনি তা করেন নি, তবে তা অপরিবর্তনীয় ডেটা স্ট্রাকচারের জন্য খুব সাধারণ ব্যবহারের ক্ষেত্রে (সাধারণভাবে পদ্ধতিগুলি উল্লেখ করার জন্য আমি উত্তরটি পরিবর্তন করেছি, কারণ সমাধানটি সর্বত্র প্রয়োগ হয়, এমনকি এটি সাধারণদের মধ্যে আরও সাধারণ হলেও)।
জোচিম সৌর

7
এটি ব্যবহার করা ভাল clone()বা Arrays.copy()এখানে?
কেভিনার্পে

যতদূর আমার মনে আছে, জোশুয়া ব্লচের "কার্যকর জাভা" অনুসারে ক্লোন () অবশ্যই পছন্দসই উপায়।
ভিনসেন্ট

1
আইটেম 13 এর শেষ বাক্য, "বিচারের ভিত্তিতে ক্লোনটি ওভাররাইড করুন": "একটি নিয়ম হিসাবে, অনুলিপি কার্যকারিতা নির্মাতারা বা কারখানাগুলি দ্বারা সর্বোত্তমভাবে সরবরাহ করা হয় this এই নিয়মের একটি উল্লেখযোগ্য ব্যতিক্রম অ্যারে, যা ক্লোন পদ্ধতিতে সেরা অনুলিপি করা হয়" "
ভিনসেন্ট

14

জাভাতে অপরিবর্তনীয় অ্যারে করার একটি উপায় রয়েছে:

final String[] IMMUTABLE = new String[0];

0 টি উপাদানযুক্ত অ্যারে (স্পষ্টতই) পরিবর্তন করা যায় না।

আপনি যদি অ্যারেতে List.toArrayরূপান্তর করতে পদ্ধতিটি ব্যবহার করে থাকেন তবে এটি আসলে কার্যকর হতে পারে List। যেহেতু একটি খালি অ্যারে কিছুটা মেমরিও নেয়, আপনি ধ্রুবক ফাঁকা অ্যারে তৈরি করে এবং সর্বদা এটি toArrayপদ্ধতিতে প্রেরণ করে সেই মেমরি বরাদ্দ সংরক্ষণ করতে পারেন । যদি অ্যারের আপনি পাস যথেষ্ট স্থান নেই যে পদ্ধতি একটি নতুন অ্যারে বরাদ্দ হবে, কিন্তু যদি এটা (তালিকা খালি) আছে, এটা অ্যারের আপনি পাশ ফিরে আসবে, আপনি যে অ্যারের যে কোনো সময় আপনাকে কল পুনরায় ব্যবহার করতে সক্ষম হবেন toArrayএকটি অন খালি List

final static String[] EMPTY_STRING_ARRAY = new String[0];

List<String> emptyList = new ArrayList<String>();
return emptyList.toArray(EMPTY_STRING_ARRAY); // returns EMPTY_STRING_ARRAY

3
তবে এটি ওপিতে এতে ডেটা সহ একটি অপরিবর্তনীয় অ্যারে অর্জন করতে সহায়তা করে না।
শ্রীধর সারনোবাত

1
@ শ্রীধর-সারনোবাত এ জাতীয় উত্তর point এটিতে ডেটা দিয়ে অবিচ্ছিন্ন অ্যারে করার জাভাতে কোনও উপায় নেই।
ব্রিগাম

1
আমি এই সহজ বাক্য গঠন আরও ভাল পছন্দ করি: ব্যক্তিগত স্ট্যাটিক ফাইনাল স্ট্রিং [] EMPTY_STRING_ARRAY = {}; (অবশ্যই "মিনি-মার্কডাউন" কীভাবে করব তা আমি বুঝতে পারি নি fig একটি প্রাকদর্শন বোতামটি দুর্দান্ত।)
ওয়েস

6

আর একটি উত্তর

static class ImmutableArray<T> {
    private final T[] array;

    private ImmutableArray(T[] a){
        array = Arrays.copyOf(a, a.length);
    }

    public static <T> ImmutableArray<T> from(T[] a){
        return new ImmutableArray<T>(a);
    }

    public T get(int index){
        return array[index];
    }
}

{
    final ImmutableArray<String> sample = ImmutableArray.from(new String[]{"a", "b", "c"});
}

কনস্ট্রাক্টরে সেই অ্যারে অনুলিপি করে কী ব্যবহার করা যায়, যেহেতু আমরা কোনও সেটার পদ্ধতি সরবরাহ করি নি?
বিজয় কুমার

ইনপুট অ্যারের সামগ্রীতে এখনও পরে পরিবর্তন করা যেতে পারে। আমরা এর মূল অবস্থাটি সংরক্ষণ করতে চাই, তাই আমরা এটি অনুলিপি করি।
আয়ারাকোড

4

জাভা 9 হিসাবে আপনি ব্যবহার করতে পারেন List.of(...), জাভাডক

এই পদ্ধতিটি একটি অপরিবর্তনীয় ফিরিয়ে দেয় Listএবং খুব দক্ষ।


3

আপনার যদি (পারফরম্যান্সের কারণে বা স্মৃতি সংরক্ষণের জন্য) 'জাভা.লং.ইনটিজার'-এর পরিবর্তে স্থানীয়' ইন্ট 'প্রয়োজন হয়, তবে সম্ভবত আপনার নিজের র‌্যাপার ক্লাসটি লিখতে হবে। নেটে বিভিন্ন ইন্টাআরে বাস্তবায়ন রয়েছে, কিন্তু কোনওটিই (আমি খুঁজে পেলাম) স্থাবর ছিল না: কোডার্স ইনট্রে , লুসিন ইনট্রে । সম্ভবত অন্যরাও আছেন।


3

গুয়ারা 22, প্যাকেজ থেকে com.google.common.primitivesআপনি তিনটি নতুন ক্লাস ব্যবহার করতে পারেন, যার তুলনায় কম মেমরির পদচিহ্ন রয়েছে ImmutableList

তাদের একজন নির্মাতাও রয়েছে। উদাহরণ:

int size = 2;
ImmutableLongArray longArray = ImmutableLongArray.builder(size)
  .add(1L)
  .add(2L)
  .build();

বা, যদি আকারটি সংকলন সময়ে জানা থাকে:

ImmutableLongArray longArray = ImmutableLongArray.of(1L, 2L);

এটি জাভা আদিমদের জন্য একটি অ্যারের অপরিবর্তনীয় দৃষ্টিভঙ্গি পাওয়ার অন্য উপায়।


1

না, এটি সম্ভব নয়। তবে, কেউ এরকম কিছু করতে পারে:

List<Integer> temp = new ArrayList<Integer>();
temp.add(Integer.valueOf(0));
temp.add(Integer.valueOf(2));
temp.add(Integer.valueOf(3));
temp.add(Integer.valueOf(4));
List<Integer> immutable = Collections.unmodifiableList(temp);

এর জন্য মোড়ক ব্যবহারের প্রয়োজন, এবং এটি একটি তালিকা, অ্যারে নয়, তবে আপনি যেটি পাবেন এটি সবচেয়ে কাছের।


4
এই সমস্ত valueOf()গুলি লিখার দরকার নেই , অটোবক্সিং সেদিকে খেয়াল রাখবে। এছাড়াও Arrays.asList(0, 2, 3, 4)আরো অনেক কিছু সংক্ষিপ্ত হতে হবে।
জোছিম সউর

@ জোয়াচিম: ব্যবহারের পয়েন্ট হ'ল valueOf()মেমরির খরচ / পুনর্ব্যবহারযোগ্যতা হ্রাস করতে অভ্যন্তরীণ পূর্ণসংখ্যার বস্তু ক্যাশে ব্যবহার করা।
এসকো

4
@ এসকো: অটোবক্সিং স্পেকটি পড়ুন। এটি ঠিক একই জিনিসটি করে, তাই এখানে কোনও পার্থক্য নেই।
জোছিম সউর

1
@ জন আপনি কখনই কোনও এনপিই পাবেন না যদিও intতা রূপান্তরিত করবেন Integer; অন্যদিকে কেবল সাবধান হতে হবে।
কলিনড

1
@ জন: আপনি ঠিক বলেছেন, এটি বিপজ্জনক হতে পারে। তবে এটিকে পুরোপুরি এড়িয়ে চলার পরিবর্তে, সম্ভবত বিপদটি বোঝা এবং এটি এড়ানো আরও ভাল।
জোচিম সৌর

1

কিছু পরিস্থিতিতে গুগল পেয়ারা লাইব্রেরি থেকে এই স্থির পদ্ধতিটি ব্যবহার করা হালকা ওজনের হবে: List<Integer> Ints.asList(int... backingArray)

উদাহরণ:

  • List<Integer> x1 = Ints.asList(0, 1, 2, 3)
  • List<Integer> x1 = Ints.asList(new int[] { 0, 1, 2, 3})

1

আপনি যদি পরিবর্তন এবং বক্সিং উভয়ই এড়াতে চান তবে বাক্স থেকে বেরোনোর ​​কোনও উপায় নেই। তবে আপনি এমন একটি শ্রেণী তৈরি করতে পারেন যা ভিতরে আদিম অ্যারে ধারণ করে এবং পদ্ধতি (গুলি) এর মাধ্যমে উপাদানগুলিতে পঠনযোগ্য অ্যাক্সেস সরবরাহ করে।


1

(ই ... উপাদানের) পদ্ধতি Java9 মাত্র একটি লাইন ব্যবহার অপরিবর্তনীয় তালিকা তৈরি করতে ব্যবহার করা যেতে পারে:

List<Integer> items = List.of(1,2,3,4,5);

উপরের পদ্ধতিটি একটি অপরিবর্তনীয় তালিকা প্রদান করে যা একটি স্বেচ্ছাসেবী সংখ্যার উপাদান রয়েছে। এবং এই তালিকায় কোনও পূর্ণসংখ্যা যুক্ত করলে java.lang.UnsupportedOperationExceptionব্যতিক্রম হবে। এই পদ্ধতিটি একটি একক অ্যারেটিকে আর্গুমেন্ট হিসাবে গ্রহণ করে।

String[] array = ... ;
List<String[]> list = List.<String[]>of(array);

0

যদিও এটি সত্য যে এটি Collections.unmodifiableList()কাজ করে, কখনও কখনও আপনার কাছে একটি বড় লাইব্রেরি থাকতে পারে যা ইতিমধ্যে অ্যারেগুলি ফেরানোর জন্য সংজ্ঞায়িত পদ্ধতি রয়েছে (যেমন String[])। এগুলি ভাঙ্গা রোধ করতে, আপনি আসলে সহায়ক অ্যারেগুলি সংজ্ঞা দিতে পারেন যা মানগুলি সংরক্ষণ করবে:

public class Test {
    private final String[] original;
    private final String[] auxiliary;
    /** constructor */
    public Test(String[] _values) {
        original = new String[_values.length];
        // Pre-allocated array.
        auxiliary = new String[_values.length];
        System.arraycopy(_values, 0, original, 0, _values.length);
    }
    /** Get array values. */
    public String[] getValues() {
        // No need to call clone() - we pre-allocated auxiliary.
        System.arraycopy(original, 0, auxiliary, 0, original.length);
        return auxiliary;
    }
}

পরীক্ষা করার জন্য:

    Test test = new Test(new String[]{"a", "b", "C"});
    System.out.println(Arrays.asList(test.getValues()));
    String[] values = test.getValues();
    values[0] = "foobar";
    // At this point, "foobar" exist in "auxiliary" but since we are 
    // copying "original" to "auxiliary" for each call, the next line
    // will print the original values "a", "b", "c".
    System.out.println(Arrays.asList(test.getValues()));

নিখুঁত নয়, তবে কমপক্ষে আপনার কাছে "সিউডো অপরিবর্তনযোগ্য অ্যারে" রয়েছে (শ্রেণির দৃষ্টিকোণ থেকে) এবং এটি সম্পর্কিত কোড ভঙ্গ করবে না।


-3

আচ্ছা .. অ্যারেগুলি ধ্রুবক হিসাবে (যদি সেগুলি হয়) ভেরিয়েন্টের পরামিতি হিসাবে পাস করতে দরকারী।


একটি "ভেরিয়েন্টের প্যারামিটার" কি? কখনো শুনি নি.
সেলসেক

2
ধ্রুবক হিসাবে অ্যারে ব্যবহার করা হয় ঠিক যেখানে লোকেরা ব্যর্থ হয়। রেফারেন্স স্থির, তবে অ্যারের সামগ্রীগুলি পরিবর্তনযোগ্য mut একজন কলার / ক্লায়েন্ট আপনার "ধ্রুবক" এর বিষয়বস্তু পরিবর্তন করতে পারে। এটি সম্ভবত আপনি মঞ্জুরি দিতে চান এমন কিছু নয়। একটি অপ্রয়োজনীয় তালিকা ব্যবহার করুন।
চার্লি কলিন্স

@ চর্লিকোলিনস এমনকি এটি প্রতিবিম্বের মাধ্যমে হ্যাক করা যেতে পারে। জাভা পরিবর্তনীয়তার দিক থেকে অনিরাপদ ভাষা ... এবং এটি কোনও পরিবর্তন হবে না।
নাম 4

2
@ সার্জবার্চ এটি সত্য, তবে প্রতিবিম্ব-ভিত্তিক হ্যাকিং করা যে কেউ এপিআই প্রকাশক তাদের অ্যাক্সেস না চেয়ে থাকতে পারে এমন জিনিসগুলি সংশোধন করে আগুন নিয়ে খেলছেন তা জানতে হবে। অন্যদিকে, যদি কোনও এপিআই কোনও ফিরিয়ে দেয় int[], কলার ধরে নিতে পারে যে তারা API এর ইন্টারনালগুলি প্রভাবিত না করেই তারা অ্যারে দিয়ে যা চান তা করতে পারে।
ডাইসকোগ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.