জাভা সংগ্রহের তালিকা কীভাবে অনুলিপি করবেন


141

আমার একটি আছে ArrayListএবং আমি এটি ঠিক কপি করতে চাই। কেউ যখন এটিকে সঠিক করে তুলতে কিছুটা সময় ব্যয় করেছিল এই ধারণা নিয়ে আমি যখন সম্ভব তখন ইউটিলিটি ক্লাস ব্যবহার করি। তাই স্বাভাবিকভাবেই, আমি Collectionsক্লাসটি শেষ করি যার একটি অনুলিপি পদ্ধতি রয়েছে।

ধরুন আমার নিম্নলিখিতগুলি রয়েছে:

List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());

Collections.copy(b,a);

এটি ব্যর্থ হয় কারণ মূলত এটি মনে করে যে bএটি ধরে রাখা যথেষ্ট বড় নয় a। হ্যাঁ আমি জানি bআকার 0 আছে তবে এটি এখন বড় হওয়া উচিত নয়? যদি আমাকে bপ্রথমে পূরণ করতে হয় তবে তা Collections.copy()আমার মনের মধ্যে একটি সম্পূর্ণ অকেজো ফাংশন হয়ে যায়। সুতরাং, একটি অনুলিপি ফাংশন প্রোগ্রামিং ব্যতীত (যা আমি এখন যাচ্ছি) এটি করার কোনও সঠিক উপায় আছে কি?


কালেকশন.কপি () এর জন্য দস্তাবেজটি বলে "গন্তব্য তালিকাটি উত্স তালিকার অন্তত লম্বা হওয়া উচিত" "
ডিজেক্লেওয়ার্থ

21
আমি গৃহীত উত্তর সঠিক বলে মনে করি না
বোজহো

3
আপনি একটি ভুল উত্তর গ্রহণ করেছেন, জ্যাস্পার ফ্লোর। আমি আন্তরিকভাবে আশা করি আপনি আপনার কোডটিতে ভুল তথ্য ব্যবহার করেন নি!
ম্যালকম

উত্তর:


115

কল করা হচ্ছে

List<String> b = new ArrayList<String>(a);

এর aমধ্যে একটি অগভীর অনুলিপি তৈরি করে b। সমস্ত উপাদান তাদের bঠিক একই ক্রমের মধ্যে উপস্থিত থাকবে a(ধরে নিলে এটির একটি আদেশ রয়েছে) had

একইভাবে, কল করা

// note: instantiating with a.size() gives `b` enough capacity to hold everything
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b, a);

এর aমধ্যে একটি অগভীর অনুলিপি তৈরি করে b। যদি প্রথম প্যারামিটার,, এর সমস্ত উপাদান অন্তর্ভুক্ত করার জন্য bপর্যাপ্ত ক্ষমতা (আকার নয়) থাকে না aতবে এটি একটি নিক্ষেপ করবে IndexOutOfBoundsException। প্রত্যাশাটি হ'ল Collections.copyকাজ করার জন্য কোনও বরাদ্দের প্রয়োজন হবে না এবং যদি থাকে তবে তা ব্যতিক্রম ছুঁড়ে দেয়। এটি অনুলিপি করা কালেকশনটি পূর্বনির্ধারিত হওয়া প্রয়োজন ( b), তবে আমি সাধারণত মনে করি না যে উপরের মতো প্রদর্শিত কন্ট্রাক্টর-ভিত্তিক বিকল্পগুলি দেওয়া প্রয়োজনীয় চেকগুলির কারণে কোনও বৈশিষ্ট্যযুক্ত পার্শ্ব প্রতিক্রিয়া নেই বলে বৈশিষ্ট্যটি তার পক্ষে উপযুক্ত।

একটি গভীর অনুলিপি তৈরি করতে List, উভয় পদ্ধতির মাধ্যমে, অন্তর্নিহিত ধরণের সম্পর্কে জটিল জ্ঞান থাকতে হবে। StringS এর ক্ষেত্রে যা জাভাতে অপরিবর্তনীয় (এবং সেই বিষয়ে NET), আপনার এমনকি একটি অনুলিপিও প্রয়োজন নেই। এর ক্ষেত্রে MySpecialObjectআপনাকে এটির গভীর অনুলিপি তৈরি করতে হবে এবং এটি জেনেরিক অপারেশন নয়।


দ্রষ্টব্য: মূলত গৃহীত উত্তরটি Collections.copyগুগলের জন্য শীর্ষ ফলাফল ছিল এবং মন্তব্যে উল্লিখিতভাবে এটি ভুল ছিল।


1
@ কনাসাস হ্যাঁ এটি করে। জাভাতে জেনেরিক "অনুলিপি" ফাংশন নেই বলে আমি বিলাপ করছি। অনুশীলনে, প্রায়শই আমি দেখতে পাই যে অন্যান্য লেখকরা তাদের ক্লাসের জন্য ক্লোন () প্রয়োগ করেননি; এটি কোনও সামগ্রীর অনুলিপি করার ক্ষমতা ছাড়াই একটি ছেড়ে দেয়। বা এর চেয়েও খারাপ, আমি কোনও বাস্তবায়িত ক্লোন পদ্ধতি দেখতে পাচ্ছি না হয় বা দুর্বল ডকুমেন্টেশন রয়েছে, যা ক্লোন ফাংশনটিকে অকেজো করে তোলে (একটি নির্ভরযোগ্য এবং ব্যবহারিক "যা হচ্ছে" তা বোঝার ক্ষেত্রে)।
ম্যালকম

133

bএর ধারণক্ষমতা 3, তবে একটি আকার 0 ArrayListরয়েছে যা কিছু ধরণের বাফার ধারণক্ষমতা রয়েছে তা বাস্তবায়ন বিশদ - এটি Listইন্টারফেসের অংশ নয় , তাই Collections.copy(List, List)এটি ব্যবহার করবেন না। এটি বিশেষ ক্ষেত্রে এটি কুরুচিপূর্ণ হবে ArrayList

মিঃ উইগলস যেমন ইঙ্গিত করেছেন, অ্যারেলিস্ট কনস্ট্রাক্টর যা সংগ্রহ গ্রহণ করে তা ব্যবহার করা উদাহরণের মধ্যে দেওয়া উপায়।

আরও জটিল পরিস্থিতিতে (যাতে আপনার আসল কোডটি ভালভাবে অন্তর্ভুক্ত থাকতে পারে) এর জন্য আপনি পেয়ারা সংগ্রহগুলি দরকারী বলে মনে করতে পারেন।


58

শুধু কর:

List a = new ArrayList(); 
a.add("a"); 
a.add("b"); 
a.add("c"); 
List b = new ArrayList(a);

অ্যারেলিস্টে এমন একজন কনস্ট্রাক্টর রয়েছে যা থেকে উপাদানগুলি অনুলিপি করতে অন্য সংগ্রহ গ্রহণ করবে


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

11
স্ট্রিংগুলির তালিকার জন্য, Stringঅনুলিপিগুলি অপরিবর্তনীয় হওয়ায় গভীর অনুলিপি গুরুত্বপূর্ণ নয় ।
ডেরেক মাহর

17

স্টিফেন কাতুলকার উত্তর (গৃহীত উত্তর) ভুল (দ্বিতীয় অংশ)। এটি ব্যাখ্যা করে যে Collections.copy(b, a);এটি একটি গভীর অনুলিপি করে, যা এটি করে না। উভয়, new ArrayList(a);এবং Collections.copy(b, a);কেবল একটি অগভীর অনুলিপি করুন। পার্থক্যটি হ'ল, কনস্ট্রাক্টর নতুন মেমরি বরাদ্দ copy(...)করে , এবং তা করে না, যেখানে আপনি অ্যারে পুনরায় ব্যবহার করতে পারেন এমন ক্ষেত্রে এটি উপযুক্ত করে তোলে, কারণ সেখানে তার কার্যকারিতা সুবিধা রয়েছে।

জাভা স্ট্যান্ডার্ড এপিআই গভীর কপিগুলির ব্যবহারকে নিরুৎসাহিত করার চেষ্টা করে, কারণ নতুন কোডাররা এটি নিয়মিতভাবে ব্যবহার করেন, এটি clone()ডিফল্টরূপে সর্বজনীন না হওয়ার অন্যতম কারণ হতে পারে bad

এর জন্য উত্স কোডটি Collections.copy(...)552 নম্বরে দেখা যাবে: http://www.java2s.com/Open-Source/Java-Docament/6.0-JDK- কোর / সংগ্রহগুলি- জার- জিপ- লগিং-regex / java / util / Collections.java.htm

আপনার যদি একটি গভীর অনুলিপি প্রয়োজন হয়, আপনাকে প্রতিটি আইটেমের জন্য লুপ এবং ক্লোন () ব্যবহার করে ম্যানুয়ালি আইটেমগুলি নিয়ে পুনরাবৃত্তি করতে হবে।


12

একটি তালিকা অনুলিপি করার সহজ উপায় হ'ল এটি নতুন তালিকার নির্মাণকারীর কাছে পৌঁছে দেওয়া:

List<String> b = new ArrayList<>(a);

b এর অগভীর কপি হবে a

উত্সটির দিকে তাকানো Collections.copy(List,List)(আমি এটি আগে কখনও দেখিনি) মনে হয় এটি সূচি দ্বারা উপাদান সূচককে মোকাবেলার জন্য be ব্যবহার List.set(int,E)এইভাবে লক্ষ্য তালিকা ইত্যাদি ইত্যাদি না বিশেষ করে javadocs আমি মানা আছে চাই থেকে পরিষ্কার লিখতে উপাদান 0 ওভার 0 ইচ্ছা উপাদান।

List<String> a = new ArrayList<>(a);
a.add("foo");
b.add("bar");

List<String> b = new ArrayList<>(a); // shallow copy 'a'

// the following will all hold
assert a.get(0) == b.get(0);
assert a.get(1) == b.get(1);
assert a.equals(b);
assert a != b; // 'a' is not the same object as 'b'

আপনি কেন 'অগভীর' অনুলিপি বলছেন? - me java
noob

4
'অগভীর অনুলিপি' দ্বারা তার অর্থ হ'ল অনুলিপিটির পরে খ-তে থাকা বস্তুগুলি ক এর অনুলিপি হিসাবে নয় in
ডিজেক্লেওয়ার্থ

1
কালেকশনস কপি () এর জাভাদোক বলেছেন "গন্তব্য তালিকাটি উত্স তালিকার অন্তত লম্বা হওয়া উচিত" "
ডিজে ক্লেওয়ার্থ

আমি অনুমান করি যে আমি ঠিক বলতে চাইছিলাম যে এটি ফাংশনটি আসলে কী করেছে তা দেখতে আমার বেশ কয়েকটা চেহারা লেগেছে এবং আমি দেখতে পাচ্ছি যে প্রশ্নকারী ঠিক কীভাবে এটির সাথে কিছুটা বিভ্রান্ত হয়ে পড়েছিল
গ্যারেথ ডেভিস

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

9
List b = new ArrayList(a.size())

আকার সেট করে না এটি প্রাথমিক ক্ষমতা নির্ধারণ করে (এটি আকার পরিবর্তন করার আগে এটি কতগুলি উপাদানের সাথে ফিট করতে পারে তা হচ্ছে)। এই ক্ষেত্রে অনুলিপি করার একটি সহজ উপায় হ'ল:

List b = new ArrayList(a);

8

যেমন হোইজুই উল্লেখ করেছেন। স্টিফেন কাতুলকার কাছ থেকে নির্বাচিত উত্তরে কালেকশনকপি সম্পর্কে একটি মন্তব্য রয়েছে যা ভুল। লেখক সম্ভবত এটি গ্রহণ করেছেন কারণ কোডের প্রথম লাইনটি তার যে অনুলিপিটি চেয়েছিল তা করছে। কালেকশনস কপির অতিরিক্ত কলটি আবার কপি করে। (অনুলিপিটির অনুলিপি দুইবার ঘটছে)।

এটি প্রমাণ করার কোড এখানে।

public static void main(String[] args) {

    List<String> a = new ArrayList<String>();
    a.add("a");
    a.add("b");
    a.add("c");
    List<String> b = new ArrayList<String>(a);

    System.out.println("There should be no output after this line.");

    // Note, b is already a shallow copy of a;
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) != b.get(i)) {
            System.out.println("Oops, this was a deep copy."); // Note this is never called.
        }
    }

    // Now use Collections.copy and note that b is still just a shallow copy of a
    Collections.copy(b, a);
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) != b.get(i)) {
            System.out.println("Oops, i was wrong this was a deep copy"); // Note this is never called.
        }
    }

    // Now do a deep copy - requires you to explicitly copy each element
    for (int i = 0; i < a.size(); i++) {
        b.set(i, new String(a.get(i)));
    }

    // Now see that the elements are different in each 
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) == b.get(i)) {
            System.out.println("oops, i was wrong, a shallow copy was done."); // note this is never called.
        }
    }
}

5

এখানে বেশিরভাগ উত্তর সমস্যাটি বুঝতে পারে না, ব্যবহারকারীরা প্রথম তালিকা থেকে দ্বিতীয় তালিকায় উপাদানগুলির একটি কপি রাখতে চান, গন্তব্য তালিকার উপাদানগুলি নতুন বস্তু এবং মূল তালিকার উপাদানগুলির উল্লেখ নয়। (অর্থাত্ দ্বিতীয় তালিকার একটি উপাদান পরিবর্তনের সাথে উত্স তালিকার সাথে সম্পর্কিত উপাদানগুলির মান পরিবর্তন করা উচিত নয়)) পরিবর্তিত অবজেক্টের জন্য আমরা অ্যারেলিস্ট (সংগ্রহ) নির্মাণকারী ব্যবহার করতে পারি না কারণ এটি সহজ তালিকার উপাদানটিকে উল্লেখ করবে এবং অনুলিপি করবে না। অনুলিপি করার সময় আপনার কাছে প্রতিটি সামগ্রীর জন্য তালিকা ক্লোনার থাকা দরকার।


5

আপনি কেবল addAllপদ্ধতিটি ব্যবহার করবেন না কেন :

    List a = new ArrayList();
         a.add("1");
         a.add("abc");

    List b = b.addAll(listA);

//b will be 1, abc

আপনার বিতে বিদ্যমান আইটেম রয়েছে বা আপনি এর পরে কিছু উপাদান দুল করতে চান এমনকি যেমন:

List a = new ArrayList();
     a.add("1");
     a.add("abc");

List b = new ArrayList();
     b.add("x");
     b.addAll(listA);
     b.add("Y");

//b will be x, 1, abc, Y

3

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

List b = new ArrayList();
b.add("aa");
b.add("bb");

List a = new ArrayList(b);

3

স্ট্রিংগুলি গভীরভাবে অনুলিপি করা যায়

List<String> b = new ArrayList<String>(a);

কারণ তারা পরিবর্তনযোগ্য। অন্য প্রতিটি অবজেক্ট নয় -> আপনার নিজের পুনরাবৃত্তি করতে হবে এবং নিজের দ্বারা একটি অনুলিপি করা দরকার।


8
এটি এখনও অগভীর অনুলিপি কারণ অ্যারের প্রতিটি উপাদান bএকই অনুরূপ Stringঅবজেক্টটিতে নির্দেশ করে a। যাইহোক, এটি গুরুত্বপূর্ণ নয় কারণ, আপনি যেমন উল্লেখ করেছেন, Stringঅবজেক্টগুলি অপরিবর্তনীয়।
ডেরেক মহর

3
private List<Item> cloneItemList(final List<Item> items)
    {
        Item[] itemArray = new Item[items.size()];
        itemArray = items.toArray(itemArray);
        return Arrays.asList(itemArray);
    }

4
দয়া করে আপনার উত্তরে কিছু ব্যাখ্যা যুক্ত করুন
সাম্পাডা

1
যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কীভাবে এবং / বা কেন এটি সমস্যার সমাধান করে তা সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করলে উত্তরের দীর্ঘমেয়াদী মান উন্নত হবে।
মাইকেল পার্কার

1

অন্য প্রতিটি অবজেক্ট নয় -> আপনার নিজের পুনরাবৃত্তি করতে হবে এবং নিজের দ্বারা একটি অনুলিপি করা দরকার।

এটি ক্লোনযোগ্য বাস্তবায়ন এড়াতে।

public class User implements Serializable, Cloneable {

    private static final long serialVersionUID = 1L;

    private String user;
    private String password;
    ...

    @Override
    public Object clone() {
        Object o = null;
        try {
          o = super.clone();
        } catch(CloneNotSupportedException e) {
        }
        return o;
     }
 }

....

  public static void main(String[] args) {

      List<User> userList1 = new ArrayList<User>();

      User user1 = new User();
      user1.setUser("User1");
      user1.setPassword("pass1");
      ...

      User user2 = new User();
      user2.setUser("User2");
      user2.setPassword("pass2");
      ...

      userList1 .add(user1);
      userList1 .add(user2);

      List<User> userList2 = new ArrayList<User>();


      for(User u: userList1){
          u.add((User)u.clone());
      }

      //With this you can avoid 
      /*
        for(User u: userList1){
            User tmp = new User();
            tmp.setUser(u.getUser);
            tmp.setPassword(u.getPassword);
            ...
            u.add(tmp);               
        }
       */

  }

2
এটি "ইউজারলিস্ট 2.এডিডি ((ব্যবহারকারী) ইউক্লোন ()) হওয়া উচিত নয়;" ?
কৃষপ্রকাশ

1

নিম্নলিখিত আউটপুট কপিরাইট কনস্ট্রাক্টর এবং কালেকশনস কপি () ব্যবহারের ফলাফল চিত্রিত করে:

Copy [1, 2, 3] to [1, 2, 3] using copy constructor.

Copy [1, 2, 3] to (smaller) [4, 5]
java.lang.IndexOutOfBoundsException: Source does not fit in dest
        at java.util.Collections.copy(Collections.java:556)
        at com.farenda.java.CollectionsCopy.copySourceToSmallerDest(CollectionsCopy.java:36)
        at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:14)

Copy [1, 2] to (same size) [3, 4]
source: [1, 2]
destination: [1, 2]

Copy [1, 2] to (bigger) [3, 4, 5]
source: [1, 2]
destination: [1, 2, 5]

Copy [1, 2] to (unmodifiable) [4, 5]
java.lang.UnsupportedOperationException
        at java.util.Collections$UnmodifiableList.set(Collections.java:1311)
        at java.util.Collections.copy(Collections.java:561)
        at com.farenda.java.CollectionsCopy.copyToUnmodifiableDest(CollectionsCopy.java:68)
        at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:20)

সম্পূর্ণ প্রোগ্রামের উত্সটি এখানে: জাভা তালিকার অনুলিপি । তবে java.util. Collections.copy () কীভাবে আচরণ করে তা দেখার জন্য আউটপুট যথেষ্ট।


1

এবং যদি আপনি গুগল পেয়ারা ব্যবহার করেন তবে এক লাইন সমাধান হ'ল

List<String> b = Lists.newArrayList(a);

এটি একটি পরিবর্তনীয় অ্যারে তালিকার উদাহরণ তৈরি করে।


1

জাভা 8 নাল-নিরাপদ হওয়ায় আপনি নিম্নলিখিত কোডটি ব্যবহার করতে পারেন।

List<String> b = Optional.ofNullable(a)
                         .map(list -> (List<String>) new ArrayList<>(list))
                         .orElseGet(Collections::emptyList);

বা সংগ্রাহক ব্যবহার করছেন

List<String> b = Optional.ofNullable(a)
                         .map(List::stream)
                         .orElseGet(Stream::empty)
                         .collect(Collectors.toList())

0

আপনি যদি কোনও বিদ্যমান সংগ্রহে কিছু মান কপি করতে ব্যবহারের ক্ষেত্রে কল্পনা করেন তবে অনুলিপি অনর্থক নয়। অর্থাৎ আপনি elementsোকানোর পরিবর্তে বিদ্যমান উপাদানগুলিকে ওভাররাইট করতে চান।

একটি উদাহরণ: a = [1,2,3,4,5] বি = [2,2,2,2,3,3,3,3,3,4,4,4,] এ কোড (বি) = [1,2,3,4,5,3,3,3,3,4,4,4]

তবে আমি এমন একটি অনুলিপি পদ্ধতি আশা করব যা উত্স এবং লক্ষ্য সংগ্রহের সূচনা সূচকের জন্য অতিরিক্ত পরামিতি, পাশাপাশি গণনার জন্য একটি প্যারামিটার গ্রহণ করবে।

জাভা বিইউ 6350752 দেখুন


-1

কেন সংগ্রহের কপি () সূচকের বাইরে সূচি ছুড়ে দেয় তা বুঝতে, যদিও আপনি গন্তব্য তালিকার ব্যাকিং অ্যারেটি যথেষ্ট পরিমাণে করেছেন (সোর্সলিস্টে আকার () কল দিয়ে) এই সম্পর্কিত প্রশ্নে অভয় যাদবের উত্তর দেখুন: কীভাবে অন্য java.util.List এ একটি java.util.List কপি করুন

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