ফিল্টার মানগুলি কেবল জাভা 8-এ ল্যাম্বদা ব্যবহার করে নালাগুলি না হলে


160

আমার কাছে অবজেক্টগুলির একটি তালিকা রয়েছে car। আমি জাভা 8 ব্যবহার করে কিছু প্যারামিটারের ভিত্তিতে এই তালিকাটি ফিল্টার করতে চাই But তবে পরামিতিটি থাকলে nullতা ছুঁড়ে দেয় NullPointerException। নাল মানগুলি কীভাবে ফিল্টার করবেন?

বর্তমান কোডটি নিম্নরূপ

requiredCars = cars.stream().filter(c -> c.getName().startsWith("M"));

এই ছোঁড়ার NullPointerExceptionযদি getName()আয় null


আপনি কি "নাল নয় কেবল ফিল্টার মানগুলি" বা "নাল মানগুলি ফিল্টার আউট" করতে চান? এটি আমার সাথে বিরোধী মনে হচ্ছে।
হোলার

3
আমি কি আপনাকে পরামর্শ দিতে পারি যে আপনি টুনাকির উত্তরটি মেনে নেবেন কারণ মনে হচ্ছে এটিই কেবল আপনার প্রশ্নের উত্তর দেয়।
মার্ক বুথ

উত্তর:


322

এই বিশেষ উদাহরণে আমি মনে করি @ টেগির এটি 100% সঠিক, এটি একটি ফিল্টারে উঠুন এবং দুটি চেক করুন। আমি Optional.ofNullablereturnচ্ছিক স্টাফ ব্যবহার করব না রিটার্ন টাইপের জন্য যুক্তি না করা সত্যিই ... তবে সত্যিকার অর্থেই এখানে বা সেখানে নয়।

আমি এটি উল্লেখ করতে চেয়েছিলাম যে java.util.Objectsএকটি বিস্তৃত ক্ষেত্রে এটির জন্য একটি দুর্দান্ত পদ্ধতি রয়েছে, তাই আপনি এটি করতে পারেন:

cars.stream()
    .filter(Objects::nonNull)

যা আপনার নাল বস্তুগুলি পরিষ্কার করে দেবে। পরিচিত নয় এমন কারও জন্য, এটি নিম্নলিখিতগুলির জন্য স্বল্প হাত:

cars.stream()
    .filter(car -> Objects.nonNull(car))

আঞ্চলিকভাবে প্রশ্নের উত্তর দিয়ে শুরু হওয়া গাড়ির নামের তালিকাটি ফেরত দিতে "M":

cars.stream()
    .filter(car -> Objects.nonNull(car))
    .map(car -> car.getName())
    .filter(carName -> Objects.nonNull(carName))
    .filter(carName -> carName.startsWith("M"))
    .collect(Collectors.toList());

শর্টহ্যান্ড ল্যাম্বডাসে অভ্যস্ত হয়ে গেলে আপনি এটিও করতে পারেন:

cars.stream()
    .filter(Objects::nonNull)
    .map(Car::getName)        // Assume the class name for car is Car
    .filter(Objects::nonNull)
    .filter(carName -> carName.startsWith("M"))
    .collect(Collectors.toList());

দুর্ভাগ্যক্রমে একবার আপনি .map(Car::getName)কেবল নামগুলির তালিকা ফিরিয়ে আনবেন, গাড়ি নয়। এত কম সুন্দর তবে পুরো প্রশ্নের উত্তর দেয়:

cars.stream()
    .filter(car -> Objects.nonNull(car))
    .filter(car -> Objects.nonNull(car.getName()))
    .filter(car -> car.getName().startsWith("M"))
    .collect(Collectors.toList());

1
মনে রাখবেন নাল গাড়ি ইস্যু নয়। এই ক্ষেত্রে, এটি নাম সম্পত্তি সম্পত্তি সৃষ্টি করে। সুতরাং Objects::nonNullএখানে ব্যবহার করা যাবে না, এবং শেষ পরামর্শে cars.stream() .filter(car -> Objects.nonNull(car.getName()))আমার বিশ্বাস হওয়া উচিত
kiedysktos

1
বিটিডাব্লু, আমার মনে cars.stream() .filter(car -> Objects.nonNull(car.getName()) && car.getName().startsWith("M"))হয় এই প্রশ্নের প্রসঙ্গে আপনার পরামর্শের সংক্ষিপ্তসার হবে
কিডিস্কটোস

3
@ কিডিস্কটোস এটি একটি ভাল বিষয় যে কলিংয়ের .startWithফলে নাল পয়েন্টারও হতে পারে। আমি যে বিষয়টিটি তৈরির চেষ্টা করছিলাম সেটি হ'ল জাভা আপনার স্ট্রিম থেকে নাল বস্তুগুলি ফিল্টার করার জন্য বিশেষত একটি পদ্ধতি সরবরাহ করে।
xbakex

@ মার্ক বুথ হ্যাঁ, স্পষ্টতই Objects.nonNullএর সমতুল্য != null, আপনার বিকল্পটি খাটো
কিডিস্কটোস

1
আপনি কি Stringগাড়ি ( Car) পরিবর্তে গাড়ির নামের তালিকা তৈরি করছেন না ?
ব্যবহারকারী1803551

59

আপনার কেবলমাত্র নামগুলির গাড়িগুলি ফিল্টার করতে হবে null:

requiredCars = cars.stream()
                   .filter(c -> c.getName() != null)
                   .filter(c -> c.getName().startsWith("M"));

3
এটি সত্যই লজ্জাজনক যে এই উত্তরটি আরও বেশি ভোট দেওয়া হয়নি কারণ এটি কেবলমাত্র উত্তরটি বলে মনে হচ্ছে যা আসলে প্রশ্নের উত্তর দেয়।
মার্ক বুথ 10

@ মারকবুথ প্রশ্ন "নাল মানগুলি কীভাবে ফিল্টার করবেন?" xbakesx দ্বারা ভাল উত্তর দেওয়া হয়েছে বলে মনে হচ্ছে।
vegemite4me

@ মারকবুথ আপনি যে তারিখগুলি সঠিক তা দেখছেন। আমার ভুল.
vegemite4me

পারফরম্যান্স অনুসারে দু'বার স্ট্রিম ফিল্টার করা ভাল বা ফিল্টারিংয়ের জন্য প্রিডিকেট আরও ভাল ব্যবহার করা উচিত? শুধু জানতে চাই.
বৈভব_শর্মা

51

প্রস্তাবিত উত্তরগুলি দুর্দান্ত। শুধু ব্যবহার নাল তালিকার ক্ষেত্রে নিয়ন্ত্রণে একটি উন্নতি সুপারিশ চাই Optional.ofNullable, জাভা 8 নতুন বৈশিষ্ট্য :

 List<String> carsFiltered = Optional.ofNullable(cars)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

সুতরাং, পুরো উত্তরটি হবে:

 List<String> carsFiltered = Optional.ofNullable(cars)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull) //filtering car object that are null
                .map(Car::getName) //now it's a stream of Strings
                .filter(Objects::nonNull) //filtering null in Strings
                .filter(name -> name.startsWith("M"))
                .collect(Collectors.toList()); //back to List of Strings

5
Ptionচ্ছিকের খারাপ ব্যবহার। শূন্য স্থানটি কখনই প্রথম স্থানে খালি সংগ্রহের প্রতিশব্দ হিসাবে ব্যবহার করা উচিত নয়।
ভিজিআর

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

1
মনে রাখবেন নাল গাড়ি ইস্যু নয়। এই ক্ষেত্রে, এটি নাম সম্পত্তি সম্পত্তি সৃষ্টি করে। তাই Objects::nonNullসমস্যার সমাধান না যেহেতু অ নাল গাড়ী নাম == থাকতে পারে নাল
kiedysktos

অবশ্যই @ কাইডিস্কটোস, তবে আমি উত্তরে এটি প্রদর্শন করতে চাইনি। তবে, আপনি যা বলছেন তা আমি গ্রহণ করছি এবং উত্তরটি সম্পাদনা করছি :)
জনি

24

আপনি একক ফিল্টার ধাপে এটি করতে পারেন:

requiredCars = cars.stream().filter(c -> c.getName() != null && c.getName().startsWith("M"));

আপনি যদি getName()বেশ কয়েকবার কল করতে না চান (উদাহরণস্বরূপ, এটি ব্যয়বহুল কল), আপনি এটি করতে পারেন:

requiredCars = cars.stream().filter(c -> {
    String name = c.getName();
    return name != null && name.startsWith("M");
});

বা আরও পরিশীলিত পদ্ধতিতে:

requiredCars = cars.stream().filter(c -> 
    Optional.ofNullable(c.getName()).filter(name -> name.startsWith("M")).isPresent());

দ্বিতীয় উদাহরণটিতে ইনলাইন প্রসারণটি আমার ব্যবহারের ক্ষেত্রে মূল্যবান ছিল
পল

3

এর শক্তিটি লাভ করা java.util.Optional#map():

List<Car> requiredCars = cars.stream()
  .filter (car -> 
    Optional.ofNullable(car)
      .map(Car::getName)
      .map(name -> name.startsWith("M"))
      .orElse(false) // what to do if either car or getName() yields null? false will filter out the element
    )
  .collect(Collectors.toList())
;

1

আপনি এটি ব্যবহার করতে পারেন

List<Car> requiredCars = cars.stream()
    .filter (t->  t!= null && StringUtils.startsWith(t.getName(),"M"))
    .collect(Collectors.toList());

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