একটি নাল-নিরাপদ তুলনাটি (বাস্তবায়ন) কীভাবে সহজ করবেন?


156

আমি compareTo()এই জাতীয় কোনও সাধারণ শ্রেণীর জন্য পদ্ধতি বাস্তবায়ন করছি ( Collections.sort()জাভা প্ল্যাটফর্ম দ্বারা প্রদত্ত অন্যান্য গুডিজ ব্যবহার করতে সক্ষম হতে ):

public class Metadata implements Comparable<Metadata> {
    private String name;
    private String value;

// Imagine basic constructor and accessors here
// Irrelevant parts omitted
}

আমি এই জিনিসগুলির প্রাকৃতিক ক্রমটি চাই : 1) নাম অনুসারে বাছাই করা এবং 2) নাম অনুসারে বাছাই করা যদি নাম একই হয়; উভয় তুলনা ক্ষেত্রে সংবেদনশীল হতে হবে। উভয় ক্ষেত্রে নাল মান পুরোপুরি গ্রহণযোগ্য, সুতরাং compareToএই ক্ষেত্রে ভঙ্গ করা উচিত নয়।

যে সমাধানটি মনে মনে আসে তা হ'ল নিম্নলিখিত পংক্তির বরাবর (আমি এখানে "গার্ড ক্লজ" ব্যবহার করছি অন্যরা হয়ত একক রিটার্ন পয়েন্ট পছন্দ করতে পারে তবে এটি সেই বিন্দুর পাশে):

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(Metadata other) {
    if (this.name == null && other.name != null){
        return -1;
    }
    else if (this.name != null && other.name == null){
        return 1;
    }
    else if (this.name != null && other.name != null) {
        int result = this.name.compareToIgnoreCase(other.name);
        if (result != 0){
            return result;
        }
    }

    if (this.value == null) {
        return other.value == null ? 0 : -1;
    }
    if (other.value == null){
        return 1;
    }

    return this.value.compareToIgnoreCase(other.value);
}

এটি কাজটি করে তবে আমি এই কোডটি নিয়ে পুরোপুরি খুশি নই। স্বীকারযোগ্যভাবে এটি খুব জটিল নয়, তবে এটি বেশ ভার্জোজ এবং ক্লান্তিকর।

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

সম্পাদনা ২-৩ : এডির ডান; উপরে "উভয় নাম নাল" কেস স্থির করে নিন

গৃহীত উত্তর সম্পর্কে

আমি ২০০৯ সালে অবশ্যই জাভা ১.6-এ এই প্রশ্নটি জিজ্ঞাসা করেছি এবং সেই সময় এডির খাঁটি জেডি কে সমাধানটি আমার পছন্দের স্বীকৃত উত্তর ছিল was আমি এখন পর্যন্ত (2017) এটিকে পরিবর্তন করতে পারি নি।

এছাড়াও তৃতীয় পক্ষের লাইব্রেরি সমাধানগুলি রয়েছে - ২০০৯ এপাচি কমন্স সংগ্রহগুলি একটি এবং একটি 2013 পেয়ারা, উভয়ই আমার দ্বারা পোস্ট করা হয়েছিল - যেটি আমি কিছু সময় পছন্দ করেছি।

আমি এখন লুকাশ ভিক্টরের ক্লিন জাভা 8 সমাধানটি গ্রহণযোগ্য উত্তর হিসাবে তৈরি করেছি। এটি অবশ্যই জাভা 8 এ পছন্দ করা উচিত এবং আজকাল জাভা 8 প্রায় সমস্ত প্রকল্পের জন্য উপলব্ধ হওয়া উচিত।


উত্তর:


173

জাভা 8 ব্যবহার করে :

private static Comparator<String> nullSafeStringComparator = Comparator
        .nullsFirst(String::compareToIgnoreCase); 

private static Comparator<Metadata> metadataComparator = Comparator
        .comparing(Metadata::getName, nullSafeStringComparator)
        .thenComparing(Metadata::getValue, nullSafeStringComparator);

public int compareTo(Metadata that) {
    return metadataComparator.compare(this, that);
}

7
আমি অ্যাপাচি কমন্স ল্যাং-এর পক্ষে জাভা 8 বিল্ট-ইন স্টাফ ব্যবহার করে সমর্থন করি তবে জাভা 8 কোডটি বেশ কুরুচিপূর্ণ এবং এখনও ভার্বোস। আমি এই মুহুর্তের জন্য org.apache.commons.lang3.builder.CompareToBuilder এর সাথে লেগে থাকব।
jschreiner

1
এটি কালেকশন.সোর্টের জন্য কাজ করে না (অ্যারেএস.এললিস্ট (নাল, ভাল 1, নাল, ভাল 2, নাল)) কারণ এটি কোনও নাল বস্তুতে তুলনা টো () কল করার চেষ্টা করবে। এটি কীভাবে কর্নার করবেন তা বোঝার চেষ্টা করে সততার সাথে সংগ্রহের কাঠামোটিতে একটি সমস্যার মতো দেখায়।
পেড্রো বোর্জেস

3
@ পেড্রোবার্জস লেখক কন্টেনার অবজেক্টগুলিকে বাছাই করার বিষয়ে জিজ্ঞাসা করেছেন যেগুলি বাছাইযোগ্য ক্ষেত্রের মালিক (যেখানে সেই ক্ষেত্রগুলি নাল হতে পারে), নাল কনটেইনার রেফারেন্সগুলি বাছাই করার বিষয়ে নয়। সুতরাং, আপনার মন্তব্যটি সঠিক Collections.sort(List)হওয়ার সাথে সাথে তালিকায় শূন্যস্থান রয়েছে যখন কাজ করে না, মন্তব্যটি প্রশ্নের সাথে প্রাসঙ্গিক নয়।
স্ক্রাববি

211

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

result = ObjectUtils.compare(firstComparable, secondComparable)

4
(@ কং: এটি নাল-সুরক্ষার যত্ন নেয় তবে ক্ষেত্রে-সংবেদনশীলতা নয় যা মূল প্রশ্নের অন্য দিক ছিল Thus সুতরাং স্বীকৃত উত্তরটি পরিবর্তন করবে না))
জোনিক

3
এছাড়াও, আমার মনে 2013 সালে অ্যাপাচি কমন্সগুলির গ্রহণযোগ্য উত্তর হওয়া উচিত নয় ((এমনকি কিছু উপ-প্রকল্পগুলি অন্যদের তুলনায় আরও ভাল রক্ষণাবেক্ষণ করা হয়)) একই জিনিস অর্জনে পেয়ারা ব্যবহার করা যেতে পারে ; দেখুন nullsFirst()/ nullsLast()
জোনিক

8
@ জোনিক আপনি কেন মনে করেন যে অ্যাপাচি কমন্স 2013 সালে গৃহীত উত্তর হওয়া উচিত নয়?
সত্যই সুন্দর

1
অ্যাপাচি কমন্সের বড় অংশ হ'ল উত্তরাধিকার / দুর্বল রক্ষণাবেক্ষণ / নিম্ন-মানের স্টাফ। এটি সরবরাহ করে বেশিরভাগ জিনিসের জন্য আরও ভাল বিকল্প রয়েছে, উদাহরণস্বরূপ পেয়ারাতে যা পুরোপুরি খুব উচ্চমানের একটি লিব এবং জেডিকে নিজেই ক্রমবর্ধমান। ২০০৫ এর আশেপাশে হ্যাঁ, অ্যাপাচি কমন্সটি বিষ্ঠা ছিল তবে আজকাল বেশিরভাগ প্রকল্পে এটির দরকার নেই। (অবশ্যই, ব্যতিক্রম আছে; উদাহরণস্বরূপ যদি কোনও কারণে আমার যদি এফটিপি ক্লায়েন্টের প্রয়োজন হয় তবে আমি সম্ভবত অ্যাপাচি কমন্স নেট-এ ব্যবহার করতাম।)
জোনিক

6
@ জোনিক, আপনি পেয়ারা ব্যবহার করে কীভাবে প্রশ্নের উত্তর দেবেন? অ্যাপাচি কমন্স ল্যাং (প্যাকেজ org.apache.commons.lang3) "লিগ্যাসি / দুর্বল রক্ষণাবেক্ষণ / নিম্নমানের" আপনার দাবিটি মিথ্যা বা সর্বোত্তম ভিত্তিহীন। কম্যান্স ল্যাং 3 বুঝতে ও ব্যবহার করা সহজ এবং এটি সক্রিয়ভাবে বজায় রয়েছে। এটি সম্ভবত আমার বেশিরভাগ ব্যবহারযোগ্য লাইব্রেরি (স্প্রিং ফ্রেমওয়ার্ক এবং স্প্রিং সিকিউরিটি বাদে) - স্ট্রিং ইউটিস ক্লাসটি নাল-নিরাপদ পদ্ধতি সহ ইনপুটটিকে সাধারণীকরণকে তুচ্ছ করে তোলে, উদাহরণস্বরূপ।
পৌল

93

আমি একটি নাল নিরাপদ তুলনামূলক প্রয়োগ করব। সেখানে কোনও বাস্তবায়ন হতে পারে, তবে এটি বাস্তবায়নের জন্য এতটা সহজ যে আমি সবসময় আমার নিজের ঘূর্ণায়মান।

দ্রষ্টব্য: উপরের আপনার তুলনাকারী, উভয় নাম যদি শূন্য হয় তবে মান ক্ষেত্রের সাথে তুলনাও করবেন না। আপনি যা চান তা আমি মনে করি না।

আমি নিম্নলিখিতগুলির মতো কিছু দিয়ে এটি বাস্তবায়ন করব:

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(final Metadata other) {

    if (other == null) {
        throw new NullPointerException();
    }

    int result = nullSafeStringComparator(this.name, other.name);
    if (result != 0) {
        return result;
    }

    return nullSafeStringComparator(this.value, other.value);
}

public static int nullSafeStringComparator(final String one, final String two) {
    if (one == null ^ two == null) {
        return (one == null) ? -1 : 1;
    }

    if (one == null && two == null) {
        return 0;
    }

    return one.compareToIgnoreCase(two);
}

সম্পাদনা: কোড নমুনায় ফিক্স টাইপস। এটি প্রথম পরীক্ষা না করার জন্য আমি পেয়েছি!

সম্পাদনা: স্থির হিসাবে নালসেফস্ট্রিংকম্পেরেটর প্রচারিত।


2
নেস্টেড "যদি" সম্পর্কিত ... আমি এই মামলার জন্য কম পাঠযোগ্য কিনা নেস্টেড খুঁজে পাই, তাই আমি এড়াতে পারি। হ্যাঁ, কখনও কখনও এটির কারণে একটি অপ্রয়োজনীয় তুলনা হবে। পরামিতিগুলির জন্য চূড়ান্ত প্রয়োজনীয় নয়, তবে এটি একটি ভাল ধারণা।
এডি

31
XOR এর মিষ্টি ব্যবহার
জেমস ম্যাকমাহন

9
@ ফিহাগ - আমি জানি এটি 3 বছরেরও বেশি সময় পেরেছে, তবে ... finalকীওয়ার্ডটি সত্যই প্রয়োজনীয় নয় (জাভা কোডটি ইতিমধ্যে যেমনটি ভার্বোস রয়েছে।) তবে এটি স্থানীয় ভার্স হিসাবে প্যারামিটারগুলির পুনরায় ব্যবহারকে রোধ করে না (একটি ভয়ানক কোডিং অনুশীলন।) হিসাবে সফ্টওয়্যার সম্পর্কে আমাদের সম্মিলিত বোঝাপড়া সময়ের সাথে সাথে আরও ভাল হয়, আমরা জানি যে ডিফল্টরূপে জিনিসগুলি চূড়ান্ত / কনস্ট্যান্ট / অবিচ্ছিন্ন হওয়া উচিত। সুতরাং আমি finalপরামিতি ঘোষণাগুলি (তবে তুচ্ছ ফাংশনটি হতে পারে) পেতে ব্যবহারের ক্ষেত্রে কিছুটা অতিরিক্ত ভার্বোসিসিটি পছন্দ করি inmutability-by-quasi-default) এটির বোধগম্যতা / রক্ষণাবেক্ষণের ওভারহেড জিনিসগুলির দুর্দান্ত স্কিমের তুলনায় নগণ্য।
luis.espinal

24
@ জামেস ম্যাকমাহন আমাকে একমত হতে হবে না। Xor (^) কেবলমাত্র সমান নয় (! =) দিয়ে প্রতিস্থাপন করা যেতে পারে। এমনকি এটি একই বাইট কোডটি সংকলন করে। ! = বনাম of এর ব্যবহার কেবল স্বাদ এবং পঠনযোগ্যতার বিষয়। সুতরাং, আপনি বিস্মিত হয়েছিলেন তা বিচার করে আমি বলব যে এটি এখানে নেই। আপনি যখন চেকসাম গণনা করার চেষ্টা করছেন তখন xor ব্যবহার করুন। অন্যান্য বেশিরভাগ ক্ষেত্রে (এটির মতো) আসুন! = ধরে থাকুন।
বিভিডিবি

5
স্ট্রিংকে টি দিয়ে টি, টি টি হিসাবে ঘোষণা করা <টি তুলনামূলক <T>> হিসাবে ঘোষিত হয়ে এই উত্তরটি প্রসারিত করা সহজ ... এবং তারপরে আমরা নিরাপদে যেকোনও তুলনামূলক তুলনামূলক বস্তুর তুলনা করতে পারি
থিয়েরি

20

পেয়ারা ব্যবহার করে আপডেট (2013) সমাধানের জন্য এই উত্তরটির নীচে দেখুন।


এই আমি শেষ পর্যন্ত সঙ্গে গিয়েছিলাম। এটি প্রমাণিত হয়েছে যে নাল-সেফ স্ট্রিং তুলনার জন্য আমাদের কাছে ইতিমধ্যে একটি ইউটিলিটি পদ্ধতি রয়েছে, তাই এর সহজ ব্যবহারটি সহজ সমাধান ছিল। (এটি একটি বড় কোডবেস; এই ধরণের জিনিস মিস করা সহজ :)

public int compareTo(Metadata other) {
    int result = StringUtils.compare(this.getName(), other.getName(), true);
    if (result != 0) {
        return result;
    }
    return StringUtils.compare(this.getValue(), other.getValue(), true);
}

এইভাবে সাহায্যকারীকে সংজ্ঞায়িত করা হয় (এটি ওভারলোডেড যাতে নালগুলি প্রথমে আসে বা শেষ হয়, আপনি যদি চান তবে এটিও নির্ধারণ করতে পারেন):

public static int compare(String s1, String s2, boolean ignoreCase) { ... }

সুতরাং এটি মূলত এডির জবাবের সমান (যদিও আমি কোনও স্ট্যাটিক সহায়ক পদ্ধতির তুলনাকারী বলব না ) এবং উজিনের খুব।

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

সম্পাদনা (২০০৯): অ্যাপাচি কমন্স সংগ্রহ সংস্করণ

আসলে, অ্যাপাচি কমন্সের ভিত্তিতে সমাধানটি NullComparatorসহজ করার একটি উপায় । শ্রেণিতে সরবরাহ করা কেস-সংবেদনশীলComparator সাথে এটি একত্রিত করুন String:

public static final Comparator<String> NULL_SAFE_COMPARATOR 
    = new NullComparator(String.CASE_INSENSITIVE_ORDER);

@Override
public int compareTo(Metadata other) {
    int result = NULL_SAFE_COMPARATOR.compare(this.name, other.name);
    if (result != 0) {
        return result;
    }
    return NULL_SAFE_COMPARATOR.compare(this.value, other.value);
}

এখন এটি বেশ মার্জিত, আমি মনে করি। (কেবল একটি ছোট সমস্যা রয়ে গেছে: কমন্স NullComparatorজেনারিকগুলি সমর্থন করে না, সুতরাং একটি চেক করা অ্যাসাইনমেন্ট নেই))

আপডেট (2013): পেয়ারা সংস্করণ

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

এই ধ্রুবকটি কোথাও রাখুন, যেমন "স্ট্রিং ইউটিলস" শ্রেণিতে:

public static final Ordering<String> CASE_INSENSITIVE_NULL_SAFE_ORDER =
    Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsLast(); // or nullsFirst()

তারপরে, এতে public class Metadata implements Comparable<Metadata>:

@Override
public int compareTo(Metadata other) {
    int result = CASE_INSENSITIVE_NULL_SAFE_ORDER.compare(this.name, other.name);
    if (result != 0) {
        return result;
    }
    return CASE_INSENSITIVE_NULL_SAFE_ORDER.compare(this.value, other.value);
}    

অবশ্যই এটি অ্যাপাচি কমন্স সংস্করণটির সাথে প্রায় একই রকম (উভয়ই জেডিকে-CASE_INSENSITIVE_ORDER ব্যবহার করে), nullsLast()একমাত্র পেয়ারা-নির্দিষ্ট জিনিস হিসাবে ব্যবহার। এই সংস্করণটি কেবল কমন্স কালেকশনের কাছে নির্ভরতা হিসাবে, পেয়ারা হিসাবে পছন্দনীয় pre ( সবাই একমত হিসাবে ।)

আপনি যদি ভাবছিলেন তবে Orderingনোট করুন এটি কার্যকর করে Comparator। বিশেষত আরও জটিল বাছাই করার প্রয়োজনের জন্য এটি বেশ সহজ, উদাহরণস্বরূপ কয়েকটি অর্ডিংস ব্যবহার করে আপনাকে শৃঙ্খলাবদ্ধ করার সুযোগ দেয় compound()। আরও পড়ুন অর্ডার পড়ুন !


2
স্ট্রিং.সিএএসআইআইএনএসআইএনএসআইটিআইভিআইপিডিআরটি সমাধানটিকে আরও পরিষ্কার করে তোলে। সুন্দর আপডেট।
প্যাট্রিক 19

2
আপনি যদি যাইহোক অ্যাপাচি কমন্স ব্যবহার করেন তবে এমন একটি ব্যবস্থা রয়েছে ComparatorChainযাতে আপনার নিজস্ব compareToপদ্ধতির প্রয়োজন হয় না ।
অ্যামিবি

13

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

আপনি যে শ্রেণিতে আগ্রহী তা হ'ল নাল তুলক । এটি আপনাকে নালগুলি উচ্চ বা নিম্ন তৈরি করতে দেয়। যখন দুটি মানটি শূন্য হয় না তখন আপনি এটি ব্যবহার করার জন্য আপনার নিজস্ব তুলকটিও দিন।

আপনার ক্ষেত্রে আপনার কাছে স্থিতিশীল সদস্যের পরিবর্তনশীল থাকতে পারে যা তুলনা করে এবং তারপরে আপনার compareToপদ্ধতিটি কেবল এটি উল্লেখ করে।

কিছু মত

class Metadata implements Comparable<Metadata> {
private String name;
private String value;

static NullComparator nullAndCaseInsensitveComparator = new NullComparator(
        new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                // inputs can't be null
                return o1.compareToIgnoreCase(o2);
            }

        });

@Override
public int compareTo(Metadata other) {
    if (other == null) {
        return 1;
    }
    int res = nullAndCaseInsensitveComparator.compare(name, other.name);
    if (res != 0)
        return res;

    return nullAndCaseInsensitveComparator.compare(value, other.value);
}

}

এমনকি যদি আপনি নিজের রোল করার সিদ্ধান্ত নেন তবে এই ক্লাসটি মনে রাখবেন কারণ নাল উপাদানগুলিকে অন্তর্ভুক্ত তালিকাগুলি অর্ডার করার সময় এটি খুব দরকারী।


ধন্যবাদ, আমি কমনস এ জাতীয় কিছু হবে আশা করেছিলাম! : এই ক্ষেত্রে, কিন্তু, আমি এটি ব্যবহার শেষ হয়নি stackoverflow.com/questions/481813/...
Jonik

আপনার স্ট্রিং.সিএএসআইএনআইএনএসআইএনএসআইটিআইভিআইপিডিআর ব্যবহার করে আপনার পদ্ধতিটি সহজ করা যেতে পারে তা বুঝতে পেরেছি; আমার সম্পাদিত ফলো-আপ উত্তর দেখুন।
জোনিক 16

এটি ভাল তবে "যদি (অন্যান্য == নাল) check" চেকটি থাকা উচিত নয়। তুলনীয় জন্য জাভাডোক বলেছেন যে তুলনা করার জন্য অন্যটি শূন্য হলে একটি নালপয়েন্টার এক্সেপশন নিক্ষেপ করা উচিত।
ড্যানিয়েল আলেকিয়ুক

7

আমি জানি যে এটি সরাসরি আপনার প্রশ্নের উত্তর নাও হতে পারে, কারণ আপনি বলেছিলেন যে নাল মানকে সমর্থন করতে হবে।

তবে আমি কেবল উল্লেখ করতে চাই যে তুলনা করার ক্ষেত্রে নালগুলি সমর্থন করা তুলনার জন্য অফিসিয়াল জাভাদোকগুলিতে বর্ণিত তুলনা চুক্তির সাথে সামঞ্জস্য নয় :

দ্রষ্টব্য যে নালটি কোনও শ্রেণীর উদাহরণ নয়, এবং e.compareTo (নাল) একটি নালপয়েন্টার এক্সসেপশন নিক্ষেপ করা উচিত যদিও e.equals (নাল) মিথ্যা প্রত্যাবর্তন করে।

সুতরাং আমি হয় নালপয়েন্টার এক্সেপশনকে স্পষ্টভাবে নিক্ষেপ করব বা নাল আর্গুমেন্টটি যখন অবজ্ঞাপূর্ণ হচ্ছে তখন প্রথমবার এটি ছুঁড়ে ফেলা যাক।


4

আপনি পদ্ধতিটি নিষ্কাশন করতে পারেন:

public int cmp(String txt, String otherTxt)
{
    if ( txt == null )
        return otjerTxt == null ? 0 : 1;

    if ( otherTxt == null )
          return 1;

    return txt.compareToIgnoreCase(otherTxt);
}

public int compareTo(Metadata other) {
   int result = cmp( name, other.name); 
   if ( result != 0 )  return result;
   return cmp( value, other.value); 

}


2
"0: 1" "" 0: -1 "হওয়া উচিত নয়?
রল্ফ ক্রিস্টেনসেন

3

আপনি আপনার শ্রেণিটি অপরিবর্তনীয় হতে ডিজাইন করতে পারেন (কার্যকর জাভা 2 য় সংস্করণ। এটির উপর একটি দুর্দান্ত বিভাগ রয়েছে, আইটেম 15: পরিবর্তনকে হ্রাস করুন) এবং নিশ্চিত করুন যে কোনও নালই সম্ভব না (এবং প্রয়োজনে নাল বস্তুর প্যাটার্নটি ব্যবহার করুন )। তারপরে আপনি এই সমস্ত চেক এড়িয়ে যেতে পারেন এবং নিরাপদে মানগুলি নাল নয় বলে ধরে নিতে পারেন।


হ্যাঁ, এটি সাধারণত একটি ভাল সমাধান এবং অনেকগুলি বিষয় সহজতর করে - তবে এখানে আমি সেই ক্ষেত্রে আরও আগ্রহী ছিলাম যেখানে নাল মান অনুমোদিত হয়, এক কারণে বা অন্য কারণে, এবং অবশ্যই বিবেচনায় নেওয়া উচিত :)
জোনিক

2

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

StringUtil.NULL_SAFE_COMPARATOR.compare(getName(), o.getName());

public class StringUtil {
    public static final Comparator<String> NULL_SAFE_COMPARATOR = new Comparator<String>() {

        @Override
        public int compare(final String s1, final String s2) {
            if (s1 == s2) {
                //Nulls or exact equality
                return 0;
            } else if (s1 == null) {
                //s1 null and s2 not null, so s1 less
                return -1;
            } else if (s2 == null) {
                //s2 null and s1 not null, so s1 greater
                return 1;
            } else {
                return s1.compareTo(s2);
            }
        }
    }; 

    public static void main(String args[]) {
        final ArrayList<String> list = new ArrayList<String>(Arrays.asList(new String[]{"qad", "bad", "sad", null, "had"}));
        Collections.sort(list, NULL_SAFE_COMPARATOR);

        System.out.println(list);
    }
}

2

আমরা জাভা 8 টি ব্যবহার করে অবজেক্টের মধ্যে নাল-বান্ধব তুলনা করতে পারি। আমি 2 টি ক্ষেত্রের সাথে একটি বালক শ্রেণি সম্পর্কে ধারণা করেছি: স্ট্রিংয়ের নাম এবং পূর্ণসংখ্যার বয়স এবং আমি প্রথমে নামগুলির সাথে তুলনা করতে চাই এবং তারপর উভয়ই সমান হলে বয়সগুলি।

static void test2() {
    List<Boy> list = new ArrayList<>();
    list.add(new Boy("Peter", null));
    list.add(new Boy("Tom", 24));
    list.add(new Boy("Peter", 20));
    list.add(new Boy("Peter", 23));
    list.add(new Boy("Peter", 18));
    list.add(new Boy(null, 19));
    list.add(new Boy(null, 12));
    list.add(new Boy(null, 24));
    list.add(new Boy("Peter", null));
    list.add(new Boy(null, 21));
    list.add(new Boy("John", 30));

    List<Boy> list2 = list.stream()
            .sorted(comparing(Boy::getName, 
                        nullsLast(naturalOrder()))
                   .thenComparing(Boy::getAge, 
                        nullsLast(naturalOrder())))
            .collect(toList());
    list2.stream().forEach(System.out::println);

}

private static class Boy {
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Boy(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "name: " + name + " age: " + age;
    }
}

এবং ফলাফল:

    name: John age: 30
    name: Peter age: 18
    name: Peter age: 20
    name: Peter age: 23
    name: Peter age: null
    name: Peter age: null
    name: Tom age: 24
    name: null age: 12
    name: null age: 19
    name: null age: 21
    name: null age: 24

1

কেউ যদি বসন্ত ব্যবহার করে তবে একটি শ্রেণি org.springframework.util.comparator. NullSafeComparator রয়েছে যা এটি আপনার জন্যও করে। এটির সাথে এটির সাথে আপনার নিজের তুলনাযোগ্য সাজান

new NullSafeComparator<YourObject>(new YourComparable(), true)

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/comparator/NullSafeComparator.html


1

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

        if(o1.name != null && o2.name != null){
            return o1.name.compareToIgnoreCase(o2.name);
        }
        // at least one is null
        return (o1.name == o2.name) ? 0 : (o1.name != null ? 1 : -1);

1
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Comparator;

public class TestClass {

    public static void main(String[] args) {

        Student s1 = new Student("1","Nikhil");
        Student s2 = new Student("1","*");
        Student s3 = new Student("1",null);
        Student s11 = new Student("2","Nikhil");
        Student s12 = new Student("2","*");
        Student s13 = new Student("2",null);
        List<Student> list = new ArrayList<Student>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s11);
        list.add(s12);
        list.add(s13);

        list.sort(Comparator.comparing(Student::getName,Comparator.nullsLast(Comparator.naturalOrder())));

        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
            Student student = (Student) iterator.next();
            System.out.println(student);
        }


    }

}

আউটপুট হয়

Student [name=*, id=1]
Student [name=*, id=2]
Student [name=Nikhil, id=1]
Student [name=Nikhil, id=2]
Student [name=null, id=1]
Student [name=null, id=2]

1

নুলসেফ তুলককে ব্যবহার করার একটি সহজ উপায় হ'ল এটির বসন্ত বাস্তবায়ন ব্যবহার করা, নীচের একটি সহজ উদাহরণ নিম্নরূপ:

public int compare(Object o1, Object o2) {
        ValidationMessage m1 = (ValidationMessage) o1;
        ValidationMessage m2 = (ValidationMessage) o2;
        int c;
        if (m1.getTimestamp() == m2.getTimestamp()) {
            c = NullSafeComparator.NULLS_HIGH.compare(m1.getProperty(), m2.getProperty());
            if (c == 0) {
                c = m1.getSeverity().compareTo(m2.getSeverity());
                if (c == 0) {
                    c = m1.getMessage().compareTo(m2.getMessage());
                }
            }
        }
        else {
            c = (m1.getTimestamp() > m2.getTimestamp()) ? -1 : 1;
        }
        return c;
    }

0

আরেকটি অ্যাপাচি অবজেক্টUtils উদাহরণ। অন্যান্য ধরণের অবজেক্টগুলিকে বাছাই করতে সক্ষম।

@Override
public int compare(Object o1, Object o2) {
    String s1 = ObjectUtils.toString(o1);
    String s2 = ObjectUtils.toString(o2);
    return s1.toLowerCase().compareTo(s2.toLowerCase());
}

0

এটি আমার বাস্তবায়ন যা আমি আমার অ্যারেলিস্টকে বাছাই করতে ব্যবহার করি। নাল ক্লাসগুলি শেষ অনুসারে বাছাই করা হয়েছে।

আমার ক্ষেত্রে, এনটিটিফোন সত্ত্বা অস্ট্রাস্ট্রিকে প্রসারিত করে এবং আমার ধারকটি তালিকা <এনটিটিএবস্ট্রাক্ট>।

নাল নিরাপদ বাছাইয়ের জন্য "তুলনাশক্তি ()" পদ্ধতি ব্যবহার করা হয়। অন্যান্য পদ্ধতিগুলি সম্পূর্ণতার জন্য রয়েছে, এটি কীভাবে তুলনা করা যায় তা দেখানো হয় f

@Nullable
private static Integer compareIfNull(EntityPhone ep1, EntityPhone ep2) {

    if (ep1 == null || ep2 == null) {
        if (ep1 == ep2) {
            return 0;
        }
        return ep1 == null ? -1 : 1;
    }
    return null;
}

private static final Comparator<EntityAbstract> AbsComparatorByName = = new Comparator<EntityAbstract>() {
    @Override
    public int compare(EntityAbstract ea1, EntityAbstract ea2) {

    //sort type Phone first.
    EntityPhone ep1 = getEntityPhone(ea1);
    EntityPhone ep2 = getEntityPhone(ea2);

    //null compare
    Integer x = compareIfNull(ep1, ep2);
    if (x != null) return x;

    String name1 = ep1.getName().toUpperCase();
    String name2 = ep2.getName().toUpperCase();

    return name1.compareTo(name2);
}
}


private static EntityPhone getEntityPhone(EntityAbstract ea) { 
    return (ea != null && ea.getClass() == EntityPhone.class) ?
            (EntityPhone) ea : null;
}

0

আপনি যদি একটি সাধারণ হ্যাক চান:

arrlist.sort((o1, o2) -> {
    if (o1.getName() == null) o1.setName("");
    if (o2.getName() == null) o2.setName("");

    return o1.getName().compareTo(o2.getName());
})

আপনি যদি তালিকার শেষের দিকে নাল রাখতে চান তবে উপরের মেটোডে এটি পরিবর্তন করুন

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