একটি অ্যারের অনুলিপি তৈরি করুন


345

আমার একটি অ্যারে রয়েছে aযা নিয়মিত আপডেট করা হচ্ছে। বলা যাক a = [1,2,3,4,5]। আমার ঠিক একটি সদৃশ অনুলিপি তৈরি করতে হবে aএবং এটি কল করতে হবে b। যদি aপরিবর্তিত হয় [6,7,8,9,10], bএখনও হওয়া উচিত [1,2,3,4,5]। এই কাজ করতে সবচেয়ে ভালো উপায় কি? আমি একটি forলুপ চেষ্টা করেছিলাম :

for(int i=0; i<5; i++) {
    b[i]=a[i]
}

তবে এটি সঠিকভাবে কাজ করছে বলে মনে হয় না। দয়া করে উন্নত পদগুলি যেমন গভীর অনুলিপি ইত্যাদি ব্যবহার করবেন না, কারণ এর অর্থ কী তা আমি জানি না।

উত্তর:


558

আপনি System.arraycopy () ব্যবহার করে চেষ্টা করতে পারেন

int[] src  = new int[]{1,2,3,4,5};
int[] dest = new int[5];

System.arraycopy( src, 0, dest, 0, src.length );

তবে, বেশিরভাগ ক্ষেত্রে ক্লোন () ব্যবহার করা ভাল:

int[] src = ...
int[] dest = src.clone();

9
চাকা পুনর্জীবিত না করার জন্য +1। এবং যতদূর আমি এটি জানি, সমাধানটি অ্যারে অনুলিপি করার ক্ষেত্রে আপনি তত দ্রুত।
ফিলিপ হুমেল

6
ক্লোন এবং অ্যারেকপি উভয়ই স্থানীয়। আমি আশা করতাম ক্লোনটি সামান্য দ্রুত হবে to পার্থক্য গুরুত্বপূর্ণ যে না।
MeBigFatGuy

5
@ ফিলিপ, @ মেবিগফ্যাটগুয়ে - কেবলমাত্র একটি বড় অ্যারের জন্য। একটি ছোট অ্যারের জন্য, সেটআপ ওভারহেডগুলির কারণে একটি অনুলিপি লুপ দ্রুততর হতে পারে। যদি আপনি জাভাদোকের দিকে নজর দেন System.arraycopy, আপনি দেখতে পাবেন যে পদ্ধতিটি শুরু হওয়ার আগে বিভিন্ন জিনিস পরীক্ষা করা দরকার। স্ট্যাটিক অ্যারে ধরণের উপর নির্ভর করে এই চেকগুলির কিছু অনুলিপি করে অনুলিপি করা হয়।
স্টিফেন সি

7
@ ফিলিপহুমেল, @ মেবিগফ্যাটগুয়ে, @ স্টিফেনসি - এখানে উত্তরগুলিতে বর্ণিত অ্যারে অনুলিপি পদ্ধতির একটি পারফরম্যান্স টেস্ট দেওয়া আছে। যে সেট আপ clone()সক্রিয় আউট 250 000 উপাদানের জন্য দ্রুততম যাবে।
অ্যাডাম

6
এটি দেখে হতাশাজনক যে এখানে সমস্ত আলোচনা মাইক্রো-পারফরম্যান্স সম্পর্কিত বিষয়ে, যা 99.999% সময় দেয় না। আরও গুরুত্বপূর্ণ পয়েন্টটি হ'ল src.clone()আরও পঠনযোগ্য এবং নতুন অ্যারে বরাদ্দ করা ও করার চেয়ে ত্রুটির পক্ষে অনেক কম সুযোগ রয়েছে arraycopy। (এবং দ্রুত হতে পারে))
ব্রায়ান গয়েটজ

231

তুমি ব্যবহার করতে পার

int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();

যেমন.


6
আমি কেবল ওপি'র বক্তব্য সাফ করছি যে: "এ যদি [6,7,8,9,10] এ পরিবর্তিত হয় তবে বি এখনও [1,2,3,4,5] হওয়া উচিত "। ওপি জানিয়েছেন তিনি লুপ ব্যবহারের চেষ্টা করেছেন কিন্তু তার পক্ষে কাজ করেননি।
হ্যারি জয়

15
Castালাই অপ্রয়োজনীয়; একটি ভাল স্ট্যাটিক বিশ্লেষক এটি সম্পর্কে সতর্ক করবে। ক্লোরিং অবশ্যই অ্যারের নতুন কপি তৈরির সেরা উপায়।
এরিকসন

5
@ মেবিগফ্যাটগুয়ে - অপির ব্যবহারের ক্ষেত্রে একই অ্যারেতে বারবার অনুলিপি করা দরকার, তাই ক্লোনটি কাজ করে না।
স্টিফেন সি

4
@ স্টেফেন সি, আমি এটি পড়িনি। আমি কেবল এটি পড়েছি যে সে একটি অনুলিপি চায় এবং তারপরে বারবার অ-স্টেস্টেড সংস্করণটি আপডেট করা হবে।
MeBigFatGuy

4
@ মেবিগফ্যাটগুয়ে - তিনি বলেছিলেন "আমার একটি অ্যারে রয়েছে যা নিয়মিত আপডেট করা হচ্ছে।" । সম্ভবত আমি এটিতে খুব বেশি পড়ছি, তবে আমি এটিকে বোঝাচ্ছি যে তিনি বারবার A কে বি তেও অনুলিপি করছেন।
স্টিফেন সি

184

আপনি যদি একটি অনুলিপি করতে চান:

int[] a = {1,2,3,4,5};

এটি যাওয়ার উপায়:

int[] b = Arrays.copyOf(a, a.length);

Arrays.copyOfa.clone()ছোট অ্যারে তুলনায় দ্রুত হতে পারে । উভয় অনুলিপি সমানভাবে দ্রুত কিন্তু ক্লোন () ফেরত দেয় Objectযাতে সংকলকটিতে একটি অন্তর্ভুক্ত কাস্ট inোকাতে হয় int[]। আপনি এটি বাইটোকোডে দেখতে পাচ্ছেন, এরকম কিছু:

ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2

62

Http://www.jorterdev.com/753/how-to-copy-arrays-in-java থেকে চমৎকার ব্যাখ্যা

জাভা অ্যারে অনুলিপি পদ্ধতি

অবজেক্ট.ক্লোন () : অবজেক্ট ক্লাস ক্লোন () পদ্ধতি সরবরাহ করে এবং যেহেতু জাভাতে অ্যারে এছাড়াও একটি অবজেক্ট, আপনি সম্পূর্ণ অ্যারে অনুলিপি অর্জন করতে এই পদ্ধতিটি ব্যবহার করতে পারেন। আপনি যদি অ্যারের আংশিক অনুলিপি চান তবে এই পদ্ধতিটি আপনার পক্ষে উপযুক্ত নয়।

System.arraycopy () : অ্যারে আংশিক অনুলিপি করার সর্বোত্তম উপায় হল সিস্টেম বর্গ অ্যারেকপি ()। এটি আপনাকে অনুলিপি করার জন্য উপাদানগুলির মোট সংখ্যা এবং উত্স এবং গন্তব্য অ্যারে সূচক অবস্থানগুলি নির্দিষ্ট করার একটি সহজ উপায় সরবরাহ করে। উদাহরণস্বরূপ System.arraycopy (উত্স, 3, গন্তব্য, 2, 5) উত্স থেকে গন্তব্যে 5 টি উপাদান অনুলিপি করবে, উত্সের তৃতীয় সূচক থেকে শুরু করে গন্তব্যের দ্বিতীয় সূচীতে।

Arrays.copyOf (): আপনি যদি অ্যারের প্রথম কয়েকটি উপাদান বা অ্যারের সম্পূর্ণ অনুলিপিটি অনুলিপি করতে চান তবে আপনি এই পদ্ধতিটি ব্যবহার করতে পারেন। স্পষ্টতই এটি System.arraycopy () এর মতো বহুমুখী নয় তবে এটি বিভ্রান্তিকর এবং সহজেই ব্যবহারযোগ্য নয়।

অ্যারেস.কপিঅফ্রেঞ্জ () : আপনি যদি কোনও অ্যারের কয়েকটি উপাদান অনুলিপি করতে চান তবে সূচনাটি 0 নয়, আপনি আংশিক অ্যারে অনুলিপি করতে এই পদ্ধতিটি ব্যবহার করতে পারেন।


35

আমার অনুভূতি আছে যে এই "অ্যারে অনুলিপি করার আরও ভাল উপায়" সত্যিই আপনার সমস্যার সমাধান করতে যাচ্ছে না।

তুমি বলো

আমি [...] এর মতো লুপের জন্য চেষ্টা করেছি তবে মনে হচ্ছে এটি সঠিকভাবে কাজ করছে না?

এই লুপটি দেখে, এটি কাজ না করার কোনও স্পষ্ট কারণ নেই ... যতক্ষণ না:

  • আপনার কোনও উপায়ে aএবং bঅ্যারেগুলি গণ্ডগোল করেছে (যেমন aএবং bএকই অ্যারেটি দেখুন), বা or
  • আপনার অ্যাপ্লিকেশনটি বহু-থ্রেডযুক্ত এবং বিভিন্ন থ্রেড aএকই সাথে অ্যারেটি পড়ছে এবং আপডেট করছে ।

উভয় ক্ষেত্রেই অনুলিপি করার বিকল্প উপায় অন্তর্নিহিত সমস্যার সমাধান করবে না।

প্রথম দৃশ্যের জন্য সংশোধন সুস্পষ্ট। দ্বিতীয় দৃশ্যের জন্য আপনাকে থ্রেডগুলি সিঙ্ক্রোনাইজ করার কিছু উপায় বের করতে হবে। পারমাণবিক অ্যারে শ্রেণিগুলি সহায়তা করে না কারণ তাদের কোনও পারমাণবিক অনুলিপি নির্মাণকারী বা ক্লোন পদ্ধতি নেই, তবে একটি আদিম মিটেক্স ব্যবহার করে সিঙ্ক্রোনাইজ করা কৌশলটি করবে।

(আপনার প্রশ্নের মধ্যে এমন কিছু ইঙ্গিত রয়েছে যা আমাকে ভাবতে পরিচালিত করে যে এটি সত্যই থ্রেড সম্পর্কিত); যেমন আপনার বক্তব্য যা aপ্রতিনিয়ত পরিবর্তিত হয়)


2
সম্মত .. সম্ভবত সত্য।
MeBigFatGuy


9

অ্যারে থেকে দৈর্ঘ্য কল করে এমন সমস্ত সমাধান, আপনার কোডটি রিডানড্যান্ট নাল চেকারসাইডার উদাহরণ যুক্ত করুন:

int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();

//What if array a comes as local parameter? You need to use null check:

public void someMethod(int[] a) {
    if (a!=null) {
        int[] b = Arrays.copyOf(a, a.length);
        int[] c = a.clone();
    }
}

আমি আপনাকে চাকাটি আবিষ্কার না করার এবং ইউটিলিটি ক্লাসটি ব্যবহার না করার পরামর্শ দিচ্ছি যেখানে সমস্ত প্রয়োজনীয় চেক ইতিমধ্যে সম্পাদিত হয়েছে। অ্যাপাচি কমন্স থেকে অ্যারে ইউটিগুলি বিবেচনা করুন। আপনার কোডটি সংক্ষিপ্ত হয়ে উঠবে:

public void someMethod(int[] a) {
    int[] b = ArrayUtils.clone(a);
}

অ্যাপাচি কমন্স আপনি সেখানে খুঁজে পেতে পারেন


8

আপনি ব্যবহার করতে পারেন Arrays.copyOfRange

উদাহরণ :

public static void main(String[] args) {
    int[] a = {1,2,3};
    int[] b = Arrays.copyOfRange(a, 0, a.length);
    a[0] = 5;
    System.out.println(Arrays.toString(a)); // [5,2,3]
    System.out.println(Arrays.toString(b)); // [1,2,3]
}

এই পদ্ধতিটি অনুরূপ Arrays.copyOfতবে এটি আরও নমনীয়। দুটোই ব্যবহার করেSystem.arraycopy ফণা অধীনে ।

দেখুন :


3

একটি অ্যারের নাল-সেফ কপির জন্য, আপনি Object.clone()এই উত্তরে প্রদত্ত পদ্ধতিটি সহ একটি alচ্ছিকও ব্যবহার করতে পারেন ।

int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);

এই সমাধানটি জটিল হয়ে যাওয়ার পরেও এটি মেমরির বর্জ্যটিরও প্রবর্তন করে এবং অ্যারেতে কোনও গোপন থাকে (উদাহরণস্বরূপ, পাসওয়ার্ড সহ বাইট অ্যারে) এটি সুরক্ষা ত্রুটিগুলিও প্রবর্তন করে কারণ মধ্যবর্তী বস্তুগুলি আবর্জনা সংগ্রহের উদঘাটন না হওয়া অবধি গাদাতে থাকবে will আক্রমণকারীদের।
ওয়েলট্রামস্যাফ

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

3

আপনি যদি কাঁচা অ্যারে সঙ্গে কাজ করতে হবে এবং যদি ArrayListতারপর Arraysআপনার যা প্রয়োজন হয়েছে। যদি আপনি উত্স কোডটি লক্ষ্য করেন তবে এগুলি হ'ল একটি অ্যারের অনুলিপি পাওয়ার সেরা উপায়। তাদের প্রতিরক্ষামূলক প্রোগ্রামিংয়ের পরিমাণ ভাল আছে কারণ System.arraycopy()আপনি যদি অযৌক্তিক পরামিতিগুলি খাওয়ান তবে পদ্ধতিটি প্রচুর পরিমাণে চেক করা ব্যতিক্রম ছুঁড়ে দেয়।

আপনি Arrays.copyOf()যেটি ব্যবহার করতে পারেন যা প্রথম থেকে Nthনতুন সংক্ষিপ্ত অ্যারেতে অনুলিপি করবে ।

public static <T> T[] copyOf(T[] original, int newLength)

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

2770
2771    public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772        T[] copy = ((Object)newType == (Object)Object[].class)
2773            ? (T[]) new Object[newLength]
2774            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775        System.arraycopy(original, 0, copy, 0,
2776                         Math.min(original.length, newLength));
2777        return copy;
2778    }

বা Arrays.copyOfRange()কৌশলটিও করবে:

public static <T> T[] copyOfRange(T[] original, int from, int to)

নির্দিষ্ট অ্যারের নির্দিষ্ট রেঞ্জটিকে একটি নতুন অ্যারেতে অনুলিপি করে। ব্যাপ্তির প্রাথমিক সূচকটি (থেকে) অবশ্যই শূন্য এবং আসল দৈর্ঘ্যের মধ্যে থাকা উচিত। আসল [থেকে] মানটি অনুলিপিটির প্রাথমিক উপাদানটিতে স্থাপন করা হয় (যদি না == আসল দৈর্ঘ্য বা == থেকে)। মূল অ্যারেতে পরবর্তী উপাদানগুলির মানগুলি অনুলিপিটিতে পরবর্তী উপাদানগুলিতে স্থাপন করা হয়। পরিসীমা (থেকে) এর চূড়ান্ত সূচক, যা অবশ্যই এর চেয়ে বড় বা সমান হতে হবে, মূল. দৈর্ঘ্যের চেয়ে বৃহত্তর হতে পারে, সেক্ষেত্রে অনুলিপিটি অনুলিপিটি অনুলিপি করা হয় অনুলিপিটি অনুলিপিটির অনুলিপিটির মূল উপাদানটির চেয়ে বড় বা সমান। দৈর্ঘ্য - থেকে। ফিরে আসা অ্যারের দৈর্ঘ্য হবে - থেকে। ফলাফল অ্যারে হুবহু মূল অ্যারে হিসাবে একই বর্গ।

3035    public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036        int newLength = to - from;
3037        if (newLength < 0)
3038            throw new IllegalArgumentException(from + " > " + to);
3039        T[] copy = ((Object)newType == (Object)Object[].class)
3040            ? (T[]) new Object[newLength]
3041            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042        System.arraycopy(original, from, copy, 0,
3043                         Math.min(original.length - from, newLength));
3044        return copy;
3045    }

আপনি দেখতে পাচ্ছেন যে, উভয়ই System.arraycopyরক্ষণাত্মক যুক্তি দিয়ে কেবল মোড়কের কাজ করে যা আপনি যা করার চেষ্টা করছেন তা বৈধ।

System.arraycopy অ্যারে অনুলিপি করার পরম দ্রুততম উপায়।


0

আমার 2 ডি অ্যারেতে একই সমস্যা ছিল এবং এখানেই শেষ হয়েছিল। আমি মূল অ্যারেটি অনুলিপি করছিলাম এবং অভ্যন্তরীণ অ্যারের মানগুলি পরিবর্তন করছিলাম, এবং যখন উভয় অনুলিপিতে মানগুলি পরিবর্তন হয়েছিল surprised মূলত উভয় অনুলিপিই অনিবার্য ছিল তবে একই অভ্যন্তরীণ অ্যারেগুলির রেফারেন্স ছিল এবং আমি যা চেয়েছিলাম তা পেতে আমাকে অভ্যন্তরীণ অ্যারের একটি কপি তৈরি করতে হয়েছিল।

এটি সম্ভবত ওপি-র সমস্যা নয়, তবে আমি আশা করি এটি এখনও সহায়ক হতে পারে।

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