জাভা 8 এ একাধিক নাল চেক


99

আমার নীচের কোডটি যা একাধিক নাল চেকের জন্য কিছুটা কুৎসিত।

String s = null;

if (str1 != null) {
    s = str1;
} else if (str2 != null) {
    s = str2;
} else if (str3 != null) {
    s = str3;
} else {
    s = str4;
}

সুতরাং আমি Optional.ofNullableনীচের মতো ব্যবহার করার চেষ্টা করেছি , তবে কেউ আমার কোড পড়ে কিনা তা বোঝা এখনও কঠিন। জাভা 8 এ করার জন্য সর্বোত্তম পন্থাটি কী।

String s = Optional.ofNullable(str1)
                   .orElse(Optional.ofNullable(str2)
                                   .orElse(Optional.ofNullable(str3)
                                                   .orElse(str4)));

জাভা 9-তে, আমরা এর Optional.ofNullableসাথে ব্যবহার করতে পারি, তবে জাভা 8-এ ORঅন্য কোনও পন্থা রয়েছে?


4
জাভা 9 orসিনট্যাক্সটি আমি সায়ার String s = Optional.ofNullable(str1) .or(() -> Optional.ofNullable(str2)) .or(() -> Optional.ofNullable(str3)) .orElse(str4);মতো দেখতে ভাল লাগে না Stream.of
নামান

4
@ ওলেভ.ভি. কিছুই ভুল নয়, ওপি ইতিমধ্যে এটি সম্পর্কে সচেতন এবং জাভা -8-এর সাথে নির্দিষ্ট কিছু সন্ধান করছে seeking
নামান

4
আমি জানি যে ব্যবহারকারী জাভা -8 নির্দিষ্ট সমাধানের জন্য জিজ্ঞাসা করছে, তবে সাধারণ নোটে আমি সাথে যাবStringUtils.firstNonBlank()
মোহাম্মদ আনিস এ

4
সমস্যাটি হ'ল জাভা 8 / স্ট্রিমগুলি এর পক্ষে সেরা সমাধান নয়। এই কোডটি সত্যই গন্ধযুক্ত যেমন একটি চুল্লী সাজানো হয় তবে আরও প্রসঙ্গ ছাড়াই এটি বলা শক্ত। শুরুর জন্য - তিনটি অবজেক্ট কেন সম্ভবত এত ঘনিষ্ঠভাবে সম্পর্কিত যা কোনও সংগ্রহের মধ্যে ইতিমধ্যে নেই?
বিল কে

4
@ মোহাম্মদআনিএসএ সেরা উত্তরটি দিতেন (মন্তব্য হিসাবে) তবে এক্ষেত্রে স্ট্রিং ইউটিলসের উত্স নির্দিষ্ট করে নি। যে কোনও হারে, যদি আপনার কাছে পৃথক স্ট্রিংগুলির একগুচ্ছ হিসাবে থাকতে হয় তবে এটিকে "ফার্স্টননব্ল্যাঙ্ক" এর মতো একটি বর্ণের পদ্ধতি হিসাবে কোডিং আদর্শ, অভ্যন্তরের বাক্য গঠনটি প্রতিটি লুপের জন্য একটি সাধারণ লুপ তৈরি করে একটি সন্ধানের সাথে ফিরে আসে নন-নাল মান তুচ্ছ এবং সুস্পষ্ট। এই ক্ষেত্রে, জাভা 8 স্ট্রিমগুলি একটি আকর্ষণীয় উপদ্রব। তারা আপনাকে ইনলাইন এবং এমন কিছু জটিল করতে প্ররোচিত করে যা একটি সাধারণ পদ্ধতি / লুপ হওয়া উচিত।
বিল কে

উত্তর:


173

আপনি এটি এর মতো করতে পারেন:

String s = Stream.of(str1, str2, str3)
    .filter(Objects::nonNull)
    .findFirst()
    .orElse(str4);

16
এই. আপনার যা প্রয়োজন তা ভেবে দেখুন, আপনার যা আছে তা নয়।
থোরবজর্ন রাভন অ্যান্ডারসন

21
গতি ওভারহেড কত? স্ট্রিম অবজেক্ট তৈরি করা, 4 টি পদ্ধতি কল করা, অস্থায়ী অ্যারে তৈরি করা ( {str1, str2, str3}) স্থানীয়ের থেকে অনেক ধীর দেখায় ifবা ?:যা জাভা রানটাইম অনুকূলিত করতে পারে। কিছু স্ট্রিম-নির্দিষ্ট অপ্টিমাইজেশন javacএবং জাভা রানটাইম যা এটিকে তত দ্রুত করে তোলে ?:? যদি তা না হয় তবে আমি এই সমাধানটি পারফরম্যান্স-সমালোচনামূলক কোডে প্রস্তাব দেব না।
পিটিএস

16
@ পিটিএস এটি ?:কোডের চেয়ে ধীর হতে পারে এবং আমি নিশ্চিত যে এটি সম্পাদন-সমালোচনামূলক কোডে এড়ানো উচিত। তবে এটি আরও বেশি পঠনযোগ্য এবং আপনার এটি অ-পারফরম্যান্স-সমালোচনামূলক কোড আইএমওতে সুপারিশ করা উচিত, যা আমি নিশ্চিত যে 99% এরও বেশি কোড তৈরি করে।
অ্যারোন

7
@pts কোনও স্ট্রিম নির্দিষ্ট অপ্টিমাইজেশান নেই, না javacরানটাইমের সময়ও নয়। এটি সাধারণ অপ্টিমাইজেশানগুলিকে বাদ দেয় না, যেমন সমস্ত কোডের ইনলাইন করা, পরে অপ্রয়োজনীয় ক্রিয়াকলাপগুলি বাদ দেয়। নীতিগতভাবে, শেষ ফলাফলটি সরল শর্তসাপেক্ষ এক্সপ্রেশনগুলির মতো দক্ষ হতে পারে, তবে এটি কখনও পাওয়া যায় না বলে অসম্ভাব্য, কারণ রানটাইমটি কেবল সর্বনিম্ন কোড পাথগুলিতে প্রয়োজনীয় প্রচেষ্টা ব্যয় করবে।
হলগার

22
দুর্দান্ত সমাধান! পাঠ্যতা কিছুটা বাড়ানোর জন্য আমি str4প্যারামিটারগুলিতে যুক্ত করতে Stream.of(...)এবং orElse(null)শেষ পর্যন্ত ব্যবহার করার পরামর্শ দেব ।
ড্যানিয়েল্প

73

টেরিনারি কন্ডিশনাল অপারেটর সম্পর্কে কী?

String s = 
    str1 != null ? str1 : 
    str2 != null ? str2 : 
    str3 != null ? str3 : str4
;

50
আসলে, তিনি "জাভা 8 এ এটি করার সর্বোত্তম পদ্ধতির সন্ধান করছেন"। এই পদ্ধতিটি জাভা 8-এ ব্যবহার করা যেতে পারে, সুতরাং এটি ওপেন "সেরা" দ্বারা কী বোঝায় এবং কোন ভিত্তিতে তিনি আরও ভাল তার সিদ্ধান্তকে ভিত্তি করে তার উপর নির্ভর করে।
Stultuske

17
আমি সাধারণত নেস্টেড টেরিনারিগুলি অপছন্দ করি তবে এটি দেখতে বেশ পরিষ্কার দেখাচ্ছে।
জলি জোকার

11
যে কেউ নেস্টেড টার্নারি অপারেটরগুলি প্রতিদিন পড়ছে না তার পক্ষে পার্স করার জন্য এটি একটি বিশাল ব্যথা।
কিউবিক

4
@ কিউবিক: আপনি যদি মনে করেন এটি পার্স করা শক্ত, তবে একটি মন্তব্য মত লিখুন // take first non-null of str1..3। এটি কী করে তা আপনি একবার জানতে পারলে কীভাবে তা সহজেই দেখা যায়।
পিটার

4
@ কিউবিক তবুও, এটি একটি সাধারণ পুনরাবৃত্তি প্যাটার্ন। আপনি একবার লাইন 2 পার্স করেছেন, আপনি যতগুলি কেস অন্তর্ভুক্ত করেন না কেন আপনি পুরো জিনিসটি পার্স করেছেন। এবং একবার হয়ে গেলে আপনি দশটি ভিন্ন মামলার অনুরূপ নির্বাচনকে সংক্ষিপ্ত এবং তুলনামূলক সহজ পদ্ধতিতে প্রকাশ করতে শিখেছেন। পরের বার আপনি একটি ?:মই দেখতে পাবেন, আপনি এটি জানেন কি করতে হবে। (BTW, ক্রিয়ামূলক প্রোগ্রামারদের হিসাবে এই জানি (cond ...)ক্লজ। এটা সবসময় গার্ড উপযুক্ত মান যখন পাহারা সত্য ব্যবহার করতে দ্বারা অনুসরণ থাকবে)
cmaster - পুনর্বহাল মনিকা

35

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

String[] strings = {str1, str2, str3, str4};
for(String str : strings) {
    s = str;
    if(s != null) break;
}

27

বর্তমান উত্তরগুলি দুর্দান্ত তবে আপনার অবশ্যই এটি ইউটিলিটি পদ্ধতিতে রাখা উচিত:

public static Optional<String> firstNonNull(String... strings) {
    return Arrays.stream(strings)
            .filter(Objects::nonNull)
            .findFirst();
}

এই পদ্ধতিটি Utilবছরের পর বছর ধরে আমার ক্লাসে রয়েছে, কোডকে আরও পরিষ্কার করে তোলে:

String s = firstNonNull(str1, str2, str3).orElse(str4);

আপনি এটিকে জেনেরিকও করতে পারেন:

@SafeVarargs
public static <T> Optional<T> firstNonNull(T... objects) {
    return Arrays.stream(objects)
            .filter(Objects::nonNull)
            .findFirst();
}

// Use
Student student = firstNonNull(student1, student2, student3).orElseGet(Student::new);

10
FWIW, এসকিউএল-এ, এই ফাংশনটিকে কোলেসেস বলা হয় , তাই আমি এটি আমার কোডেও বলি। এটি আপনার পক্ষে কার্যকর কিনা আপনি এসকিউএলকে কতটা পছন্দ করেন তা নির্ভর করে।
টম অ্যান্ডারসন

5
আপনি যদি এটি কোনও ইউটিলিটি পদ্ধতিতে রেখে যাচ্ছেন তবে আপনি এটি দক্ষ করে তুলতে পারেন।
টড সেলাই

4
@ টডসওয়েল, আপনার অর্থ কী?
গুস্তাভো সিলভা

5
@ গুস্তাভোসিলভা টড সম্ভবত সম্ভবত এটির একটি ইউটিলিটি পদ্ধতি হ'ল Arrays.stream()আমি যখন একটি forএবং একটি দিয়ে একই কাজ করতে পারি তখন ব্যবহার করার কোন মানে নেই != null, যা আরও দক্ষ। এবং টড ঠিক হবে। যাইহোক, আমি যখন এই পদ্ধতিটি কোড করেছিলাম তখন আমি ওপির মতো জাভা 8 বৈশিষ্ট্যগুলি ব্যবহার করে এটি করার একটি উপায় খুঁজছিলাম so
ওয়ালেন

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

13

আমি একটি সহায়ক ফাংশন ব্যবহার করি, এরকম কিছু

T firstNonNull<T>(T v0, T... vs) {
  if(v0 != null)
    return v0;
  for(T x : vs) {
    if (x != null) 
      return x;
  }
  return null;
}

তাহলে এই ধরণের কোড হিসাবে লেখা যেতে পারে

String s = firstNonNull(str1, str2, str3, str4);

4
অতিরিক্ত v0পরামিতি কেন ?
tobias_k

4
@ টোবিয়াস_ কে অতিরিক্ত প্যারামিটারটি যখন ভারার্গস ব্যবহার করা হয় তখন জাভাতে 0 বা তার চেয়ে বেশি বা 1 টির বেশি আর্গুমেন্টের প্রয়োজন হয় id (কার্যকর জাভা, এডি। 3 এর আইটেমটি দেখুন, যা minউদাহরণ হিসাবে ব্যবহার করে )) আমি এখানে কম উপযুক্ত তা নিশ্চিত নই।
নিক

4
@ নিক হ্যাঁ, আমি অনুমান করেছিলাম, তবে ফাংশনটি ঠিক তেমনি কাজ করবে (বাস্তবে ঠিক একই আচরণ করবে) এটি ছাড়া।
tobias_k

4
অতিরিক্ত প্রথম তর্কটি পাস করার মূল কারণগুলির মধ্যে একটি হ'ল অ্যারে পাস করার সময় আচরণ সম্পর্কে স্পষ্ট হওয়া। এই ক্ষেত্রে, আমি firstNonNull(arr)আরারটি ফিরে যেতে চাই যদি এটি শূন্য না হয়। যদি এটি হয় তবে firstNonNull(T... vs)এটির পরিবর্তে আরারে প্রথম অ-নাল এন্ট্রি ফিরে আসবে।
মাইকেল অ্যান্ডারসন

4

আপনি চান যতগুলি উপাদান প্রয়োগ করা যেতে পারে এমন একটি সমাধান হতে পারে:

Stream.of(str1, str2, str3, str4)
      .filter(Object::nonNull)
      .findFirst()
      .orElseThrow(IllegalArgumentException::new)

আপনি নীচের মত একটি সমাধান কল্পনা করতে পারেন, তবে প্রথমটি non nullityসমস্ত উপাদানগুলির জন্য নিশ্চিত করে

Stream.of(str1, str2, str3).....orElse(str4)

6
অথবা str4এটি আসলে নাল হয়ে অনুপ্রেরণা
নামান '

4
@ নালপয়েন্টার বা নাল orElseNullযদি একই পরিমাণে হয় str4
tobias_k

3

আপনি স্ট্রিংয়ের একটি অ্যারেতে সমস্ত স্ট্রিংগুলি একসাথে করতে পারেন তারপরে লুপটি পরীক্ষা করার জন্য লুপটি পরীক্ষা করার জন্য একবার এটি বরাদ্দ হয়ে গেলে break ধরে নিই যে এস 1, এস 2, এস 3, এস 4 হ'ল স্ট্রিংস।

String[] arrayOfStrings = {s1, s2, s3};


s = s4;

for (String value : arrayOfStrings) {
    if (value != null) { 
        s = value;
        break;
    }
}

কোনওটি বরাদ্দ না থাকলে ডিফল্টর জন্য এস 4 এ শর্তে ফেলে দিতে সম্পাদিত।


আপনি বাদ দিয়েছেন s4(বা str4), যা sশেষ পর্যন্ত বরাদ্দ করা উচিত , এমনকি যদি এটি শূন্য হয়।
ডিসপ্লেনেম

3

পদ্ধতি ভিত্তিক এবং সহজ।

String getNonNull(String def, String ...strings) {
    for(int i=0; i<strings.length; i++)
        if(strings[i] != null)
             return s[i];
    return def;
}

এবং এটি হিসাবে ব্যবহার করুন:

String s = getNonNull(str4, str1, str2, str3);

অ্যারেগুলির সাথে এটি করা সহজ এবং দেখতে সুন্দর দেখাচ্ছে।


0

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

String s = ObjectUtils.firstNonNull(str1, str2, str3, str4);

ObjectUtils.firstNonNull(T...)এই উত্তরটি থেকে ব্যবহার নেওয়া হয়েছিল । সম্পর্কিত প্রশ্নে বিভিন্ন পন্থাও উপস্থাপন করা হয়েছিল ।

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