অ্যারেলিস্ট বা স্ট্রিং অ্যারে থেকে সমস্ত নাল উপাদানগুলি কীভাবে সরিয়ে নেওয়া যায়?


187

আমি এর মতো একটি লুপ দিয়ে চেষ্টা করি

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

তবে এটি সুন্দর নয়। কেউ আমাকে আরও ভাল সমাধান প্রস্তাব করতে পারেন?


আরও ভাল সিদ্ধান্ত নেওয়ার জন্য কিছু কার্যকর মানদণ্ড:

লুপ করার সময়, লুপ এবং আইট্রেটার পারফরম্যান্স টেস্টের জন্য


2
ব্যবহার Iterator? জাভা-ডক খনন করুন। download.oracle.com/javase/6/docs/api/java/util/…
নিশান্ত

উত্তর:


365

চেষ্টা করুন:

tourists.removeAll(Collections.singleton(null));

জাভা এপিআই পড়ুন । কোডটি java.lang.UnsupportedOperationExceptionঅপরিবর্তনীয় তালিকার জন্য নিক্ষেপ করবে (যেমন তৈরি করা হয়েছে Arrays.asList); দেখতে এই উত্তরটি আরো বিস্তারিত জানার জন্য।


9
টাইম জটিলতা List.removeAll()হয় এন ^ 2 । কথা মাত্র.
হেমন্ত

8
জাভা 8 বা তার পরে, নীচে @ মার্ককের উত্তর দেখুন।
অ্যান্ডি থমাস

2
@ হেমন্ত আপনি কীভাবে সেই সময়ের জটিলতা পেয়েছিলেন তা ব্যাখ্যা করতে পারেন? কারণ এটা বেশ দেখায় O(n)উভয়ের জন্য আমাকে ArrayListএবং LinkedList
হেলদার পেরেইরা

1
@ হেল্ডারপেরীরা আমার মনে হয় না যে এটি এই ক্ষেত্রে হওয়া উচিত , যেহেতু উত্স (লাইন 349) উভয় তালিকার মধ্য দিয়ে লুপ করে ( contains()পুরো অ্যারেটি লুপ করে) এবং যেহেতু এটি singletonকেবলমাত্র একটি উপাদান হবে N * 1 = N। তবে সাধারণত এটি হবে N^2
মাইরা

6
@ হেমন্ত না এটা না এটি n * মিটার যেখানে মি হ'ল উপাদানের সংখ্যা এই ক্ষেত্রে একক নাল যা 1 হয় is এটি হে (এন)। আপনি এখানে উত্স কোডটি দেখতে পারেন এবং এটি তালিকাতে একবারে পড়তে এবং লিখতে দেখবেন, উপাদানগুলি সরানোটির জন্য অ্যাকাউন্টে সরানো।
টাটারাইজ

116

2015 পর্যন্ত, এটি সেরা উপায় (জাভা 8):

tourists.removeIf(Objects::isNull);

দ্রষ্টব্য: এই কোডটি java.lang.UnsupportedOperationExceptionঅপরিবর্তনীয় তালিকা সহ স্থির আকারের তালিকার (যেমন অ্যারে.এএসলিস্ট দিয়ে তৈরি) নিক্ষেপ করবে ।


1
"সেরা" কোন উপায়ে? এটি অন্যান্য পদ্ধতির চেয়ে দ্রুত? বা বংশবৃদ্ধির গুণে এটি আরও বেশি পাঠযোগ্য?
অ্যান্ডি টমাস

15
কেবল ব্রিভিটির কারণে নয়, কারণ এটি আরও প্রকাশিত। আপনি এটি প্রায় পড়তে পারেন: "পর্যটকদের কাছ থেকে, বস্তুটি শূন্য হলে অপসারণ করুন"। এছাড়াও, পুরানো উপায়টি একক নাল বস্তু সহ একটি নতুন সংগ্রহ তৈরি করছে এবং তারপরে অন্যটির থেকে সংগ্রহের সামগ্রীগুলি অপসারণ করতে বলছে। কিছুটা হ্যাক মনে হচ্ছে, ভাবছেন না? গতি সম্পর্কে, আপনার একটি বক্তব্য আছে, তালিকাটি যদি সত্যিই বড় হয় এবং পারফরম্যান্স একটি উদ্বেগ হয় তবে আমি উভয় উপায়ে পরীক্ষা করার পরামর্শ দেব। আমার অনুমানটি removeIfএটি দ্রুততর হবে তবে এটি একটি অনুমান।
মার্চজি

1
Arrays.asListঅপরিবর্তনীয় নয় । এটি নির্দিষ্ট আকারের।
টারবনফ

@ তুরবানফ হ্যাঁ, আপনি অবশ্যই ঠিক বলেছেন। এটি কেবল স্থির-আকার, আমি উত্তরটি আপডেট করব।
মার্ক

46
list.removeAll(Collections.singleton(null));

এটা তোলে ছোঁড়ার হবে UnsupportedException আপনি Arrays.asList উপর এটি ব্যবহার করা হয়েছে কারণ এটি আপনাকে দিতে অপরিবর্তনীয় কপি তাই এটি পরিবর্তন করা যায় না। কোড নীচে দেখুন। এটি মিউটেবল কপি তৈরি করে এবং কোনও ব্যতিক্রম ছুঁড়ে না ফেলে।

public static String[] clean(final String[] v) {
    List<String> list = new ArrayList<String>(Arrays.asList(v));
    list.removeAll(Collections.singleton(null));
    return list.toArray(new String[list.size()]);
}

18

দক্ষ না, তবে সংক্ষিপ্ত

while(tourists.remove(null));

1
দুর্ভাগ্যক্রমে, আপনার সমাধানটি কেবল আমার জন্য কাজ করেছিল ... ধন্যবাদ!
Pkmmte

সহজ এবং দ্রুত

5
@ মিমরহে বাস্তবের বিপরীতে, আসলেই। আপনার একটি বড় তালিকা থাকলে ভয়ানক ধীর।
Gewure

18

আপনি যদি অপরিবর্তনীয় ডেটা অবজেক্ট পছন্দ করেন, বা আপনি যদি ইনপুট তালিকার জন্য ধ্বংসাত্মক হতে চান না, তবে আপনি পেয়ারার পূর্বাভাসগুলি ব্যবহার করতে পারেন।

ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))

7
 for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

ট্র্যাভারিংয়ের সময় যখন আপনাকে উপাদানগুলি মুছতে হবে তখন এটি আরও কার্যকর হতে পারে। কাকতালীয় বিষয় হল আমি ব্যবহার করার চেষ্টা করার চেয়ে উপাদানগুলিকে বাতিল করছি removeAll(..null..)। ধন্যবাদ!
মোস্তফা

আপনি মানগুলি স্থির করে শেষে স্থির করে দেওয়ার চেয়ে আরও ভাল হতে পারেন। সরানোর সমস্ত ব্যাচরেমো তালিকায় স্থানান্তরিত হয়, একটি পঠন এবং লেখার অবস্থানের সাথে তালিকাকে একবারে পুনরাবৃত্তি করে, রিডকে মুভিং করে তবে যখন লেখাটি শূন্য হয়ে যায় তখন লেখাটি নয়। .remove () সেখানে প্রতিবার যখন বলা হবে তখন পুরো অ্যারেটিকে অ্যারেকপি করতে হবে।
তাতারাইজ

4

প্রাক জাভা 8 আপনার ব্যবহার করা উচিত:

tourists.removeAll(Collections.singleton(null));

জাভা-পরবর্তী 8 ব্যবহার:

tourists.removeIf(Objects::isNull);

এখানে কারণ সময় জটিলতা। অ্যারেগুলির সাথে সমস্যাটি হ'ল একটি অপসারণ অপারেশন সম্পূর্ণ করতে O (n) সময় নিতে পারে। সত্যিই জাভাতে এটি খালি জায়গা প্রতিস্থাপনের জন্য সরানো হচ্ছে এমন উপাদানগুলির একটি অ্যারে অনুলিপি। এখানে দেওয়া আরও অনেকগুলি সমাধান এই সমস্যাটিকে ট্রিগার করবে। পূর্বেরটি টেকনিক্যালি ও (এন * মি) যেখানে মিটার 1 কারণ এটি সিঙ্গলটন নাল: তাই ও (এন)

আপনার সিঙ্গলটনের সমস্তটি অপসারণ করা উচিত, অভ্যন্তরীণভাবে এটি একটি ব্যাচআরমোভ () করে যা একটি পড়ার অবস্থান এবং লেখার অবস্থান রাখে। এবং তালিকা পুনরাবৃত্তি। যখন এটি একটি নালকে আঘাত করে, এটি কেবল 1 দ্বারা পঠনের অবস্থানকে পুনরাবৃত্তি করে they যখন তারা একই হয় এটি পাস হয়, যখন তারা আলাদা হয় তখন মানগুলি অনুলিপি করার সাথে সাথে চলতে থাকে। তারপরে শেষে এটি আকারে ছাঁটাই হয়।

এটি কার্যকরভাবে অভ্যন্তরীণভাবে এটি করে:

public static <E> void removeNulls(ArrayList<E> list) {
    int size = list.size();
    int read = 0;
    int write = 0;
    for (; read < size; read++) {
        E element = list.get(read);
        if (element == null) continue;
        if (read != write) list.set(write, element);
        write++;
    }
    if (write != size) {
        list.subList(write, size).clear();
    }
}

যা আপনি স্পষ্টভাবে দেখতে পাচ্ছেন এটি একটি ও (এন) অপারেশন।

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


for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

যদিও এটি যথেষ্ট যুক্তিসঙ্গত বলে মনে হচ্ছে, পুনরাবৃত্তির উপর .remove () অভ্যন্তরীণভাবে কল করে:

ArrayList.this.remove(lastRet);

যা আবার অপসারণের মধ্যে ও (এন) অপারেশন। এটি একটি System.arraycopy () করে যা আপনি যা চান তা আবার নয়, যদি আপনি গতি সম্পর্কে চিন্তা করেন। এটি এটিকে n ^ 2 করে তোলে।

এছাড়াও আছে:

while(tourists.remove(null));

যা ও (এম * এন ^ 2)। এখানে আমরা কেবল তালিকাটি পুনরাবৃত্তি করি না। আমরা পুরো তালিকাটির পুনরাবৃত্তি করি, প্রতিবার আমরা শূন্যের সাথে মেলে। তারপরে আমরা অপসারণটি সম্পাদন করতে System.arraycopy () করতে n / 2 (গড়) অপারেশন করি। আপনি বেশ আক্ষরিকভাবে, মানগুলি এবং শূন্য মানগুলির সাথে আইটেমগুলির মধ্যে পুরো সংগ্রহটি বাছাই করতে পারেন এবং কম সময়ে শেষটি ছাঁটাই করতে পারেন। আসলে, এটি সমস্ত ভাঙ্গাগুলির জন্য সত্য। কমপক্ষে তত্ত্বের ক্ষেত্রে, আসল system.arraycopy আসলে অনুশীলনে একটি এন অপারেশন নয়। তত্ত্বের ক্ষেত্রে তত্ত্ব এবং অনুশীলন একই জিনিস; অনুশীলনে তারা হয় না।


3

nullথেকে সমস্ত মান মুছে ফেলার একটি সহজ উপায় রয়েছে collectionYou আপনাকে removeAll()পদ্ধতিতে প্যারামিটার হিসাবে নালযুক্ত একটি সংগ্রহ করতে হবে

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);

এটি আমার পক্ষে সবচেয়ে ভাল কাজ করেছে। এটি আপনাকে আপনার "ফিল্টার অ্যারে" তে সহজেই একাধিক এন্ট্রি যুক্ত করতে দেয় যা মূল সংগ্রহের সরানোর সমস্ত পদ্ধতিতে চলে যায়।

3

Objectsবর্গ একটি আছে nonNull Predicateযে সঙ্গে ব্যবহার করা যেতে পারে filter

উদাহরণ স্বরূপ:

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());

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

3

জাভা 8 ব্যবহার করে, আপনি stream()এবং এটি ব্যবহার করে এটি করতে পারেনfilter()

tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())

অথবা

tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())

আরও তথ্যের জন্য: জাভা 8 - স্ট্রিম


1
এই সমাধানটি অপরিবর্তনীয় অনুলিপি হিসাবে কাজ করছে - -> <স্ট্রিং> তালিকান তালিকা = অ্যারে.এএসলিস্ট ("টেস্ট 1", নাল, "পরীক্ষা"); ..... খুব! ধন্যবাদ
অনুরাগ_বিএইচএস

2

অ্যারেলিস্ট থেকে ডিফল্ট নাল মান সরিয়ে ফেলার এটি সহজ উপায়

     tourists.removeAll(Arrays.asList(null));  

অন্যথায় স্ট্রিং মান "নাল" অ্যারেলিস্ট থেকে সরান

       tourists.removeAll(Arrays.asList("null"));  

1

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


2
জাভাডোকের মতে, trimToSizeএ এর বিষয়বস্তুগুলি সংশোধন করে না ArrayList। এটি যদি অ্যান্ড্রয়েডে আলাদা হয় তবে এটি সম্ভবত একটি বাগ।
ফেবিয়ান

1

সমস্ত নাল মান মুছে ফেলার জন্য আমরা একইটির জন্য পুনরাবৃত্তকারী ব্যবহার করতে পারি।

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
    if(itr.next() == null){
        itr.remove();
    }
}

1

আমি স্ট্রিম ইন্টারফেসটি একসাথে স্ট্রিম অপারেশন সংগ্রহ এবং একটি নতুন তালিকা উত্পন্ন করার জন্য একটি সহায়ক-পদ্ধতির সাথে ব্যবহার করেছি।

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}

2
tourists.stream().filter(s -> s != null).collect(Collectors.toList());
1ac0

1

মূলত আমি এটি ব্যবহার করছি:

list.removeAll(Collections.singleton(null));

তবে আমি জাভা 8 শিখার পরে, আমি এটিতে স্যুইচ করেছি:

List.removeIf(Objects::isNull);

0

ব্যবহার জাভা 8 এই স্ট্রিম, সমান্তরাল প্রবাহ এবং ব্যবহার নানাভাবে সম্পাদনা করা যেতে পারে removeIfপদ্ধতি:

List<String> stringList = new ArrayList<>(Arrays.asList(null, "A", "B", null, "C", null));
List<String> listWithoutNulls1 = stringList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
List<String> listWithoutNulls2 = stringList.parallelStream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); //[A,B,C]
stringList.removeIf(Objects::isNull); //[A,B,C]

সমান্তরাল স্ট্রিম উপলভ্য প্রসেসরের ব্যবহার করবে এবং যুক্তিসঙ্গত আকারের তালিকাগুলির জন্য প্রক্রিয়াটি গতি বাড়িয়ে তুলবে। স্ট্রিমগুলি ব্যবহারের আগে এটি সর্বদা বেঞ্চমার্ককে পরামর্শ দেওয়া হয়।


0

@ লিথিয়াম উত্তরের মতো তবে "তালিকায় নাল টাইপ নাও থাকতে পারে" ত্রুটি নিক্ষেপ করে না:

   list.removeAll(Collections.<T>singleton(null));

0
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.