জাভাতে প্রথম নন-মানটি কীভাবে পাবেন?


153

এসকিউএল এর COALESCEফাংশনের জাভা সমপরিমাণ কি আছে ? এটি হল, বেশ কয়েকটি ভেরিয়েবলের প্রথম নন-মানটি ফেরত দেওয়ার কোনও উপায় আছে কি?

যেমন

Double a = null;
Double b = 4.4;
Double c = null;

আমি একরকম একটি বিবৃতি যে প্রথম অ নাল মান ফিরে আসবে চাই a, bএবং c- এই ক্ষেত্রে, এটা আবার ফিরে আসবে b, অথবা 4.4। (স্কেল পদ্ধতি মতো কিছু - ফিরুন COALESCE(a,b,c))। আমি জানি যে আমি এটির মতো স্পষ্ট করে কিছু করতে পারি:

return a != null ? a : (b != null ? b : c)

তবে আমি ভাবলাম এটি সম্পাদন করার জন্য কোনও অন্তর্নির্মিত, গৃহীত কোনও কার্যকারিতা রয়েছে কিনা।


3
আপনার কাছে এই জাতীয় কোনও ফাংশনের প্রয়োজন হবে না কারণ আপনি জেনারালি 'সি' গণনা করবেন না যদি 'বি' এর উত্তর চান তবে has যেমন আপনি কেবল একটি রাখার জন্য সম্ভাব্য উত্তরের একটি তালিকা তৈরি করবেন না।
পিটার লরে 21

কেভেট: সমস্ত আরডিবিএমএস শর্ট সার্কিট COALESCE এ নেই। ওরাকল সম্প্রতি এটি করা শুরু করেছে।
অ্যাডাম জেন্ট

3
@ BrainSlugs83 সিরিয়াসলি? জাভা উচিত?
দিমিত্রি জিনজবার্গ

উত্তর:


108

না, নেই।

আপনি পেতে পারেন নিকটতম হ'ল:

public static <T> T coalesce(T ...items) {
    for(T i : items) if(i != null) return i;
    return null;
}

দক্ষ কারণে, আপনি নিম্নলিখিত হিসাবে সাধারণ কেসগুলি পরিচালনা করতে পারেন:

public static <T> T coalesce(T a, T b) {
    return a == null ? b : a;
}
public static <T> T coalesce(T a, T b, T c) {
    return a != null ? a : (b != null ? b : c);
}
public static <T> T coalesce(T a, T b, T c, T d) {
    return ...
}

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

কুল। ধন্যবাদ। সেক্ষেত্রে আমি সম্ভবত এই ক্ষেত্রে নেস্টেড শর্তসাপেক্ষ অপারেটরদের সাথে
লেগে থাকব

8
কোডে "ভয়ঙ্কর চেহারা" শর্তসাপেক্ষ ব্লক ছাড়াই আমি এখনও এটি একটি ব্যক্তিগত সহায়ক পদ্ধতিতে টেনে আনতে পারি - "এটি কী করে?" এইভাবে, যদি আপনার আবার কখনও এটি ব্যবহার করার প্রয়োজন হয়, আপনি পদ্ধতিটি ইউটিলিটি ক্লাসে স্থানান্তর করতে আপনার আইডিইতে রিফ্যাক্টরিং সরঞ্জামগুলি ব্যবহার করতে পারেন। নামযুক্ত পদ্ধতিটি কোডের উদ্দেশ্যকে ডকুমেন্ট করতে সহায়তা করে যা সর্বদা একটি ভাল জিনিস, আইএমও। (এবং নন ভার-
আরোগুলি

10
সাবধান: ইন coalesce(a, b), যদি bএকটি জটিল অভিব্যক্তি এবং aনয় null, bএখনও মূল্যায়িত করা হয়। এটি:? শর্তসাপেক্ষ অপারেটরের ক্ষেত্রে নয়। এই উত্তর দেখুন ।
পাং

পারফরম্যান্সের কারণে নিরবচ্ছিন্নভাবে কল করার আগে প্রতিটি যুক্তির যথার্থ হিসাব করা দরকার
ইভান জি


59

যদি পরীক্ষা করার জন্য কেবল দুটি ভেরিয়েবল থাকে এবং আপনি পেয়ারা ব্যবহার করছেন তবে আপনি MoreObjects.firstNonNull (টি টি প্রথম, টি দ্বিতীয়) ব্যবহার করতে পারেন ।


49
অবজেক্টস.ফর্স্টননল কেবল দুটি যুক্তি গ্রহণ করে; পেয়ারা সমতুল্য কোন ভ্যারাগস নেই। এছাড়াও, এটি দুটি নাল ফাঁকা থাকলে এটি একটি নলপয়েন্টারএক্সেপশন নিক্ষেপ করে - এটি পছন্দসই বা নাও হতে পারে।

2
ভাল মন্তব্য, জ্যাক। এই নালপয়েন্টার এক্সসেপশন প্রায়শই অবজেক্টস.ফর্স্টননল ব্যবহার সীমাবদ্ধ করে। তবে একেবারেই নালগুলি এড়ানোর জন্য এটি পেয়ারার পদ্ধতি।
আন্তন শ্যাচস্তনি

4
সেই পদ্ধতিটি এখন অবচয় করা
ডেভিডব্বাস্টার 48


51

যদি পরীক্ষার জন্য মাত্র দুটি উল্লেখ থাকে এবং আপনি জাভা 8 ব্যবহার করেন তবে আপনি ব্যবহার করতে পারেন

Object o = null;
Object p = "p";
Object r = Optional.ofNullable( o ).orElse( p );
System.out.println( r );   // p

আপনি যদি স্থির Oচ্ছিক আমদানি করেন তবে প্রকাশটি খুব খারাপ নয় not

দুর্ভাগ্যক্রমে severalচ্ছিক পদ্ধতিতে আপনার "বেশ কয়েকটি ভেরিয়েবল" এর ক্ষেত্রে সম্ভব নয়। পরিবর্তে আপনি ব্যবহার করতে পারেন:

Object o = null;
Object p = null;
Object q = "p";

Optional<Object> r = Stream.of( o, p, q ).filter( Objects::nonNull ).findFirst();
System.out.println( r.orElse(null) );   // p

23

এলইএস 2 এর উত্তর অনুসরণ করে আপনি ওভারলোডেড ফাংশনটি কল করে দক্ষ সংস্করণে কিছু পুনরাবৃত্তি দূর করতে পারেন:

public static <T> T coalesce(T a, T b) {
    return a != null ? a : b;
}
public static <T> T coalesce(T a, T b, T c) {
    return a != null ? a : coalesce(b,c);
}
public static <T> T coalesce(T a, T b, T c, T d) {
    return a != null ? a : coalesce(b,c,d);
}
public static <T> T coalesce(T a, T b, T c, T d, T e) {
    return a != null ? a : coalesce(b,c,d,e);
}

5
সুন্দর জন্য +1। সাধারণ লুপের উপর দক্ষতার উপকার সম্পর্কে নিশ্চিত নয়, তবে আপনি যদি এইভাবে কোনও ক্ষুদ্র দক্ষতা অর্জন করতে চলেছেন তবে এটি সম্ভবত সুন্দরও হতে পারে।
কার্ল ম্যানাস্টার

3
এইভাবে ওভারলোড হওয়া ভেরিয়েন্টগুলি লেখার জন্য এটি অনেক কম বেদনাদায়ক এবং কম ত্রুটিযুক্ত করে তোলে!
লেস 2

2
দক্ষ সংস্করণটির বিন্দুটি হ'ল মেমরিটি ব্যবহার করে কোনও অ্যারের বরাদ্দ না করা varargs। এখানে, আপনি প্রতিটি নেস্টেড coalesce()কলের জন্য স্ট্যাক ফ্রেম তৈরি করে স্মৃতি নষ্ট করছেন । কলিং coalesce(a, b, c, d, e)গণনা করতে 3 স্ট্যাক ফ্রেম তৈরি করে।
লুক

10

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

কিছু এই মত ফাংশন

public static <T> T coalesce(T ...items) 

ব্যবহার করা উচিত তবে বাইট কোডটি সংকলনের আগে একটি প্রিপ্রসেসর থাকা উচিত যা এই "কোলেসেস ফাংশন" এর ব্যবহারগুলি খুঁজে পায় এবং এটির মতো নির্মাণের সাথে প্রতিস্থাপন করে

a != null ? a : (b != null ? b : c)

আপডেট 2014-09-02:

জাভা 8 এবং ল্যাম্বডাসকে ধন্যবাদ জাভাতে সত্যিকারের একত্রিত হওয়ার সম্ভাবনা রয়েছে! গুরুতর বৈশিষ্ট্য সহ: নির্দিষ্ট প্রয়োজন কেবল তখনই মূল্যায়ন করা হয় - যদি পূর্বেরটি শূন্য না হয় তবে নিম্নলিখিতগুলির মূল্যায়ন করা হয় না (পদ্ধতিগুলি বলা হয় না, গণনা বা ডিস্ক / নেটওয়ার্ক ক্রিয়াকলাপগুলি সম্পন্ন হয় না)।

আমি এটি সম্পর্কে একটি নিবন্ধ লিখেছিলাম জাভা 8: coalesce - hledáme neNULLové hodnoty - (চেক ভাষায় লিখিত, তবে আমি আশা করি যে কোডের উদাহরণগুলি সবার জন্য বোধগম্য)।


1
দুর্দান্ত নিবন্ধ - যদিও এটি ইংরেজি থাকলে ভাল লাগবে।
কোয়ান্টাম

1
ব্লগ পৃষ্ঠা সম্পর্কে এমন কিছু আছে যা গুগল অনুবাদ সাথে কাজ করে না। :-(
হেয়ারআফডডগ

5

পেয়ারা দিয়ে আপনি করতে পারেন:

Optional.fromNullable(a).or(b);

যা NPE নিক্ষেপ না করলে উভয় aএবং bহয় null

সম্পাদনা: আমি ভুল ছিলাম, এটি এনপিই ফেলে দেয়। মিশাল আইজমজিয়া মন্তব্য করেছেন সঠিক উপায়টি হ'ল:

Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull();

1
হেই, এটি করে:java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
মিশাল আইজমাজিয়া

1
এটি কৌতুকটি করে:Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
মিশাল আইজমাজিয়া

4

কেবল সম্পূর্ণতার জন্য, "বেশ কয়েকটি ভেরিয়েবল" কেসটি সত্যই সম্ভব, যদিও এটি মার্জিত নয়। উদাহরণস্বরূপ, ভেরিয়েবলের জন্য o, pএবং q:

Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )

দয়া করে ব্যবহার করে নোট orElseGet()ক্ষেত্রে যে দোসর o, pএবং qভেরিয়েবল কিন্তু এক্সপ্রেশন পারেন দামী বা অবাঞ্ছিত পার্শ্ব প্রতিক্রিয়া সঙ্গে নয়।

সর্বাধিক সাধারণ ক্ষেত্রে coalesce(e[1],e[2],e[3],...,e[N])

coalesce-expression(i) ==  e[i]  when i = N
coalesce-expression(i) ==  Optional.ofNullable( e[i] ).orElseGet(()-> coalesce-expression(i+1) )  when i < N

এটি অত্যধিক দীর্ঘ এক্সপ্রেশন তৈরি করতে পারে। যাইহোক, যদি আমরা ছাড়া একটি বিশ্বের কাছে সরানোর চেষ্টা করছেন null, তাহলে v[i]হয় সম্ভবত ইতিমধ্যে ধরনের Optional<String>, যেমন কেবল বিরোধিতা String। এক্ষেত্রে,

result= o.orElse(p.orElse(q.get())) ;

বা মত প্রকাশের ক্ষেত্রে:

result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;

তদ্ব্যতীত, যদি আপনি একটি কার্মিক-ঘোষণামূলক শৈলী থেকে সরানোর হয়, o, p, এবং qধরনের হওয়া উচিত Supplier<String>মত:

Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;

এবং তারপরে সম্পূর্ণ coalesceকমে যায় o.get()

আরও দৃ concrete় উদাহরণের জন্য:

Supplier<Integer> hardcodedDefaultAge= ()-> 99 ;
Supplier<Integer> defaultAge= ()-> defaultAgeFromDatabase().orElseGet( hardcodedDefaultAge ) ;
Supplier<Integer> ageInStore= ()-> ageFromDatabase(memberId).orElseGet( defaultAge ) ;
Supplier<Integer> effectiveAge= ()-> ageFromInput().orElseGet( ageInStore ) ;

defaultAgeFromDatabase(), ageFromDatabase()এবং ageFromInput()ইতিমধ্যে Optional<Integer>স্বাভাবিকভাবে ফিরে আসবে ।

এবং তারপর coalesceহয়ে effectiveAge.get()বা শুধু effectiveAgeআমরা সন্তুষ্ট যদি Supplier<Integer>

আইএমএইচও, জাভা 8 এর সাথে আমরা আরও বেশি সংখ্যক কোড এর মতো কাঠামোগত দেখতে পাব, কারণ এটি একই সাথে অত্যন্ত স্ব-বর্ণনামূলক এবং দক্ষ, বিশেষত আরও জটিল ক্ষেত্রে।

আমি এমন একটি ক্লাস মিস করি Lazy<T>যা Supplier<T>কেবলমাত্র একবারে আহ্বান জানায় তবে অলসতা, পাশাপাশি সংজ্ঞা Optional<T>(যেমন Optional<T>- Optional<T>অপারেটর, বা এমনকি Supplier<Optional<T>>)।


4

আপনি এটি চেষ্টা করতে পারেন:

public static <T> T coalesce(T... t) {
    return Stream.of(t).filter(Objects::nonNull).findFirst().orElse(null);
}

এই প্রতিক্রিয়া উপর ভিত্তি করে


3

আপনি যখন কোনও ব্যয়বহুল পদ্ধতির মূল্যায়ন এড়াতে চান তখন সরবরাহকারীরা কীভাবে ব্যবহার করবেন?

এটার মত:

public static <T> T coalesce(Supplier<T>... items) {
for (Supplier<T> item : items) {
    T value = item.get();
    if (value != null) {
        return value;
    }
    return null;
}

এবং তারপরে এটি ব্যবহার করে:

Double amount = coalesce(order::firstAmount, order::secondAmount, order::thirdAmount)

আপনি দুটি, তিন বা চারটি যুক্তি দিয়ে কলগুলির জন্য ওভারলোডেড পদ্ধতিগুলিও ব্যবহার করতে পারেন।

এছাড়াও, আপনি এই জাতীয় কিছু সহ স্ট্রিমগুলি ব্যবহার করতে পারেন:

public static <T> T coalesce2(Supplier<T>... s) {
    return Arrays.stream(s).map(Supplier::get).filter(Objects::nonNull).findFirst().orElse(null);
}

প্রথম যুক্তিটি কেন একটি Supplierমোড়ক কেন এটি যেভাবেই পরিদর্শন করা হবে? অভিন্নতার স্বার্থে?
Inego

0

কেমন:

firstNonNull = FluentIterable.from(
    Lists.newArrayList( a, b, c, ... ) )
        .firstMatch( Predicates.notNull() )
            .or( someKnownNonNullDefault );

জাভা অ্যারেলিস্টটি সুবিধামত নাল এন্ট্রিগুলিকে অনুমতি দেয় এবং এই অভিব্যক্তিটি বিবেচনার জন্য নির্বিশেষে সামঞ্জস্যপূর্ণ। (এই ফর্মটিতে, বিবেচিত সমস্ত বস্তু একই ধরণের হওয়া দরকার))


-3
Object coalesce(Object... objects)
{
    for(Object o : object)
        if(o != null)
            return o;
    return null;
}

2
Godশ্বর আমি জেনেরিককে ঘৃণা করি। ব্যাট থেকে ঠিক কী বোঝাতে চেয়েছিল তা আমি দেখেছি। তিনি একই জিনিসটি করছেন (এবং সম্ভবত "আরও ভাল") এটি বুঝতে আমার দুবার @ এলইএস 2 এর দিকে নজর দিতে হয়েছিল! স্পষ্টতার জন্য +1
বিল কে

হ্যাঁ, জেনেরিকগুলি হ'ল উপায়। তবে আমি জটিলতার সাথে এতটা পরিচিত নই।
এরিক

10
জেনেরিকস শিখার সময় :-)। @ এলইএস 2 এর উদাহরণ এবং এর মধ্যে কিছুটা পার্থক্য নেই, অবজেক্টের পরিবর্তে টি ব্যতীত। কোনও ক্রিয়াকলাপ তৈরি করার জন্য -1 যা ফেরতের মানটি ডাবলে ফেরত দিতে বাধ্য করবে। এছাড়াও সমস্ত ক্যাপগুলিতে একটি জাভা পদ্ধতির নামকরণের জন্য, যা এসকিউএল-তে ভাল হতে পারে, তবে জাভাতে এটি ভাল শৈলী নয়।
আভি 4'10

1
আমি বুঝতে পারি যে অল ক্যাপগুলি খারাপ অভ্যাস। আমি কেবল ওপিটি দেখিয়েছিলাম যে তারা অনুরোধ করা নামে একটি ফাংশন কীভাবে লিখবেন। সম্মত, অভিনেতাদের কাছে ফিরে Doubleআসা আদর্শ থেকে দূরে। আমি ঠিক জানি না যে স্ট্যাটিক ফাংশনগুলিকে টাইপ পরামিতি দেওয়া যেতে পারে। আমি ভেবেছিলাম এটি কেবল ক্লাস ছিল।
এরিক 20
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.