একাধিক ক্ষেত্র দ্বারা কীভাবে বস্তুর তুলনা করা যায়


237

ধরে নিন আপনার কাছে কয়েকটি বস্তু রয়েছে যার কয়েকটি ক্ষেত্র তাদের সাথে তুলনা করা যেতে পারে:

public class Person {

    private String firstName;
    private String lastName;
    private String age;

    /* Constructors */

    /* Methods */

}

সুতরাং এই উদাহরণে, আপনি যখন জিজ্ঞাসা যদি:

a.compareTo(b) > 0

আপনি জিজ্ঞাসা করতে পারেন যে খ এর আগে নামটি খ এর আগে আসে, বা যদি কোনও খ এর চেয়ে বড় হয়, ইত্যাদি ...

অপ্রয়োজনীয় নড়বড়ে বা ওভারহেড যোগ না করে এই ধরণের অবজেক্টের মধ্যে একাধিক তুলনা সক্ষম করার সবচেয়ে সহজ উপায় কী?

  • java.lang.Comparable ইন্টারফেস কেবল একটি ক্ষেত্রের সাথে তুলনা করতে দেয়
  • অসংখ্য তুলনা পদ্ধতি যোগ করার পদ্ধতি (অর্থাত compareByFirstName(), compareByAge(), ইত্যাদি ...) আমার মতে বিশৃঙ্খল করা হয়।

সুতরাং এটি সম্পর্কে সবচেয়ে ভাল উপায় কি?


3
কেন এটি সিডব্লিউ? এটি পুরোপুরি বৈধ প্রোগ্রামিং প্রশ্ন।
এলি

2
আপনি কি জানেন যে তুলনামূলক আপনার পছন্দ মতো ক্ষেত্রের সাথে তুলনা করতে দেয়?
ডিজেক্লেওয়ার্থ

উত্তর:


81

আপনি Comparatorদুটি Personবস্তুর তুলনা করে এমন একটি বাস্তবায়ন করতে পারেন এবং আপনি যতগুলি ক্ষেত্র পছন্দ করতে পারেন তা পরীক্ষা করতে পারেন। আপনি আপনার তুলনাকারীতে একটি পরিবর্তনশীল রাখতে পারেন যা কোন ক্ষেত্রের সাথে তুলনা করতে হবে তা বলবে, যদিও এটি কেবল একাধিক তুলনামূলক লিখতে সহজ হবে।


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

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

399

জাভা 8 সহ:

Comparator.comparing((Person p)->p.firstName)
          .thenComparing(p->p.lastName)
          .thenComparingInt(p->p.age);

আপনার যদি অ্যাকসেসর পদ্ধতি থাকে:

Comparator.comparing(Person::getFirstName)
          .thenComparing(Person::getLastName)
          .thenComparingInt(Person::getAge);

যদি কোনও শ্রেণি তুলনামূলক প্রয়োগ করে তবে এই জাতীয় তুলনামূলক তুলনামূলক পদ্ধতিতে ব্যবহার করা যেতে পারে:

@Override
public int compareTo(Person o){
    return Comparator.comparing(Person::getFirstName)
              .thenComparing(Person::getLastName)
              .thenComparingInt(Person::getAge)
              .compare(this, o);
}

5
বিশেষত the (Person p)ালাই শৃঙ্খলিত তুলকদের জন্য গুরুত্বপূর্ণ।
membersound

5
বিপুল সংখ্যক অবজেক্টের তুলনা করার সময় এটি কতটা দক্ষ, উদাহরণস্বরূপ বাছাই করার সময়? এটি কি Comparatorপ্রতিটি কলে নতুন দৃষ্টান্ত তৈরি করতে হবে?
jjurm

4
আমি একটি নালপয়েন্টার এক্সসেপশন পেয়েছি যখন আমি তুলনা করছি এমন ক্ষেত্রগুলির মধ্যে একটি স্ট্রিংয়ের মতো নাল। এই তুলনা বিন্যাসটি রাখার জন্য তবে কি এটিকে নাল নিরাপদে থাকতে দেওয়া আছে?
21

3
@jjurm .thenComparing(Person::getLastName, Comparator.nullsFirst(Comparator.naturalOrder()))- প্রথম ক্ষেত্র নির্বাচক, তারপরে তুলনাকারী
gavenkoa

2
@jjurm যখন আপনি এটি ব্যবহার করেন compareToউপরের মতো দেখানো Comparatorহয় প্রতিটি সময় পদ্ধতিটি বলা হয়। আপনি একটি বেসরকারী স্থিতিশীল চূড়ান্ত ক্ষেত্রে তুলক সংরক্ষণ করে এটি প্রতিরোধ করতে পারে।
গ্যান্ডালফ

165

আপনি বাস্তবায়ন করা উচিত Comparable <Person>। ধরে নিলে সমস্ত ক্ষেত্র নালাগুলি হবে না (সরলতার জন্য), সেই বয়সটি একটি অন্তর্নির্মিত এবং তুলনা র‌্যাঙ্কিং প্রথম, শেষ, বয়স, compareToপদ্ধতিটি বেশ সহজ:

public int compareTo(Person other) {
    int i = firstName.compareTo(other.firstName);
    if (i != 0) return i;

    i = lastName.compareTo(other.lastName);
    if (i != 0) return i;

    return Integer.compare(age, other.age);
}

10
আপনি যদি তুলনীয় <পার্সন> প্রয়োগ করেন তবে পদ্ধতিটি তুলনা করুন (ব্যক্তি পি) .. মনে হচ্ছে এই উত্তরটি তুলনাকারীর তুলনায় <T o1, T o2> পদ্ধতির সাথে মিশে গেছে
মাইকে

5
এটি সুপারিশ করা হয় না। আপনার একাধিক ক্ষেত্র থাকলে তুলক ব্যবহার করুন।
ইন্ডিকা

1
এই মুহুর্তে এটিই সেরা সমাধান, (আরও বেশি
তুলকের

4
@ ইন্ডিকা, আমি কৌতূহলী: কেন এটি সুপারিশ করা হয় না? একাধিক সম্পত্তি ব্যবহারের তুলনা করা আমার কাছে পুরোপুরি সূক্ষ্ম বলে মনে হচ্ছে।
আর্স-লঙ্গা-ভিটা-ব্রাভিস

4
@ আরস-লঙ্গা-ভিটা-ব্রাভিস, আপনি যদি তুলনামূলক ব্যবহার করছেন তবে বাছাইয়ের যুক্তি অবশ্যই একই শ্রেণিতে থাকতে হবে যার বস্তুগুলি সাজানো হচ্ছে তাই একে অবজেক্টের প্রাকৃতিক ক্রম বলা হয়। তুলনামূলক ব্যবহারের সাহায্যে আপনি ব্যক্তি শ্রেণির বাইরে কাস্টম বাছাইয়ের যুক্তি লিখতে পারেন। আপনি যদি ব্যক্তির বস্তুগুলির কেবল তার প্রথম নাম বা পদবি দিয়ে তুলনা করতে চান তবে আপনি এই যুক্তিটি ব্যবহার করতে পারবেন না। আপনাকে এটি আবার লিখতে হবে,
indika

78

( একাধিক ক্ষেত্রের ভিত্তিতে জাভাতে অবজেক্টের তালিকাগুলি বাছাই করার উপায়গুলি থেকে )

এই টুকরোটিতে কার্যকারী কোড

জাভা 8 ল্যাম্বদা ব্যবহার করে (10 এপ্রিল, 2019 যোগ করা হয়েছে)

জাভা 8 ল্যাম্বডা দ্বারা এটি সুন্দরভাবে সমাধান করে (যদিও পেয়ারা এবং অ্যাপাচি কমন্স এখনও আরও নমনীয়তার প্রস্তাব দিতে পারে):

Collections.sort(reportList, Comparator.comparing(Report::getReportKey)
            .thenComparing(Report::getStudentNumber)
            .thenComparing(Report::getSchool));

নীচে @ gaoagong এর উত্তর ধন্যবাদ

অগোছালো এবং সংশ্লেষিত: হাতে বাছাই করা

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        int sizeCmp = p1.size.compareTo(p2.size);  
        if (sizeCmp != 0) {  
            return sizeCmp;  
        }  
        int nrOfToppingsCmp = p1.nrOfToppings.compareTo(p2.nrOfToppings);  
        if (nrOfToppingsCmp != 0) {  
            return nrOfToppingsCmp;  
        }  
        return p1.name.compareTo(p2.name);  
    }  
});  

এর জন্য প্রচুর টাইপিং, রক্ষণাবেক্ষণ প্রয়োজন এবং এটি ত্রুটিযুক্ত।

প্রতিবিম্বিত উপায়: বিন কমপারেটর দিয়ে বাছাই করা

ComparatorChain chain = new ComparatorChain(Arrays.asList(
   new BeanComparator("size"), 
   new BeanComparator("nrOfToppings"), 
   new BeanComparator("name")));

Collections.sort(pizzas, chain);  

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

সেখানে পৌঁছনো: গুগল পেয়ারার তুলনাচিহ্নের সাথে বাছাই করা

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        return ComparisonChain.start().compare(p1.size, p2.size).compare(p1.nrOfToppings, p2.nrOfToppings).compare(p1.name, p2.name).result();  
        // or in case the fields can be null:  
        /* 
        return ComparisonChain.start() 
           .compare(p1.size, p2.size, Ordering.natural().nullsLast()) 
           .compare(p1.nrOfToppings, p2.nrOfToppings, Ordering.natural().nullsLast()) 
           .compare(p1.name, p2.name, Ordering.natural().nullsLast()) 
           .result(); 
        */  
    }  
});  

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

অ্যাপাচি কমন্স তুলনাটোবিল্ডারের সাথে বাছাই করা হচ্ছে

Collections.sort(pizzas, new Comparator<Pizza>() {  
    @Override  
    public int compare(Pizza p1, Pizza p2) {  
        return new CompareToBuilder().append(p1.size, p2.size).append(p1.nrOfToppings, p2.nrOfToppings).append(p1.name, p2.name).toComparison();  
    }  
});  

পেয়ারার তুলনাচাঁইনের মতো এই লাইব্রেরি ক্লাসটি একাধিক ক্ষেত্রগুলিতে সহজেই সাজান, তবে নাল মানগুলির জন্য ডিফল্ট আচরণকে (যেমন 1, a, b, z, নাল) সংজ্ঞায়িত করে। তবে আপনি নিজের তুলনামূলক সরবরাহ না করে আপনি অন্য কোনও কিছু নির্দিষ্ট করতে পারবেন না।

এইভাবে

শেষ পর্যন্ত এটি স্বাদে নেমে আসে এবং নমনীয়তার জন্য প্রয়োজনীয়তা (পেয়ারা'র তুলনাচয়ন) বনাম সংক্ষিপ্ত কোড (অ্যাপাচি'র কমপিটারটোবিল্ডার)।

বোনাস পদ্ধতি

আমি একটা চমৎকার সমাধান পাওয়া যে সম্মিলন একাধিক comparators অগ্রাধিকার ক্রমানুসারে CodeReview উপর একটি MultiComparator:

class MultiComparator<T> implements Comparator<T> {
    private final List<Comparator<T>> comparators;

    public MultiComparator(List<Comparator<? super T>> comparators) {
        this.comparators = comparators;
    }

    public MultiComparator(Comparator<? super T>... comparators) {
        this(Arrays.asList(comparators));
    }

    public int compare(T o1, T o2) {
        for (Comparator<T> c : comparators) {
            int result = c.compare(o1, o2);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }

    public static <T> void sort(List<T> list, Comparator<? super T>... comparators) {
        Collections.sort(list, new MultiComparator<T>(comparators));
    }
}

অবশ্যই অবশ্যই অ্যাপাচি কমন্স সংগ্রহগুলির এর জন্য ইতিমধ্যে একটি ব্যবহার রয়েছে:

ComparatorUtils.chainedComparator (comparatorCollection)

Collections.sort(list, ComparatorUtils.chainedComparator(comparators));

22

@ পেট্রিক একাধিক ক্ষেত্রকে একটানা বাছাই করতে তুলনামূলক চেইন চেষ্টা করুন

একটি তুলনাকারী চেইন এমন তুলনামূলক যা এক বা একাধিক তুলনাকে ক্রমানুসারে গুটিয়ে রাখে। ComparatorChain প্রতিটি তুলনাকারীকে ক্রমানুসারে কল করে না হয় 1 পর্যন্ত) যে কোনও একক তুলক একটি শূণ্য ফলাফল প্রদান করে (এবং তারপরে ফলাফলটি ফিরে আসে) বা 2) তুলনামূলক চাইন অবসন্ন হয় (এবং শূন্য ফিরে আসে)। এই ধরণের বাছাইটি এসকিউএল-তে বহু-কলাম বাছাইয়ের সাথে খুব সমান এবং এই শ্রেণিটি কোনও তালিকা বাছাই করার সময় জাভা ক্লাসগুলিকে সেই ধরণের আচরণ অনুকরণ করতে দেয়।

এসকিউএল-এর মতো বাছাইয়ের সুবিধার্থে তালিকার যে কোনও একক তুলকের ক্রমটি বিপরীত হতে পারে।

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

ComparatorChain এর উদাহরণগুলি সিঙ্ক্রোনাইজ করা হয় না। শ্রেণিটি নির্মাণের সময় থ্রেড-নিরাপদ নয়, তবে সমস্ত সেটআপ কার্যক্রম শেষ হওয়ার পরে একাধিক তুলনা করা থ্রেড-নিরাপদ।


20

আপনি সর্বদা অন্য যে বিকল্পটি বিবেচনা করতে পারেন তা হ'ল অ্যাপাচি কমন্স। এটি প্রচুর বিকল্প সরবরাহ করে।

import org.apache.commons.lang3.builder.CompareToBuilder;

উদা:

public int compare(Person a, Person b){

   return new CompareToBuilder()
     .append(a.getName(), b.getName())
     .append(a.getAddress(), b.getAddress())
     .toComparison();
}


10
import com.google.common.collect.ComparisonChain;

/**
 * @author radler
 * Class Description ...
 */
public class Attribute implements Comparable<Attribute> {

    private String type;
    private String value;

    public String getType() { return type; }
    public void setType(String type) { this.type = type; }

    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }

    @Override
    public String toString() {
        return "Attribute [type=" + type + ", value=" + value + "]";
    }

    @Override
    public int compareTo(Attribute that) {
        return ComparisonChain.start()
            .compare(this.type, that.type)
            .compare(this.value, that.value)
            .result();
    }

}

1
আমি এই কৌশলটি অনেক পছন্দ করি। ধন্যবাদ!
মিঃ পলিহর্ইল

সবচেয়ে কার্যকর উপায়! ধন্যবাদ
জাকারিয়া বোয়াজা

8

যাঁরা জাভা 8 স্ট্রিমিং এপিআই ব্যবহার করতে পারবেন তাদের পক্ষে এখানে একটি ন্যাটার অ্যাপ্রোচ রয়েছে যা এখানে ভালভাবে নথিভুক্ত রয়েছে: লাম্বডাস এবং বাছাই

আমি সি # লিনকিউ এর সমতুল্য সন্ধান করছিলাম:

.ThenBy(...)

আমি জাভা 8-এ তুলনামূলকটিতে খুঁজে পেয়েছি:

.thenComparing(...)

সুতরাং এখানে স্নিপেট যা অ্যালগরিদম প্রদর্শন করে।

    Comparator<Person> comparator = Comparator.comparing(person -> person.name);
    comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));

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

এখানে রেফারেন্সের জন্য পূর্ণ ইউনিট পরীক্ষা দেওয়া আছে:

@Test
public void testChainedSorting()
{
    // Create the collection of people:
    ArrayList<Person> people = new ArrayList<>();
    people.add(new Person("Dan", 4));
    people.add(new Person("Andi", 2));
    people.add(new Person("Bob", 42));
    people.add(new Person("Debby", 3));
    people.add(new Person("Bob", 72));
    people.add(new Person("Barry", 20));
    people.add(new Person("Cathy", 40));
    people.add(new Person("Bob", 40));
    people.add(new Person("Barry", 50));

    // Define chained comparators:
    // Great article explaining this and how to make it even neater:
    // http://blog.jooq.org/2014/01/31/java-8-friday-goodies-lambdas-and-sorting/
    Comparator<Person> comparator = Comparator.comparing(person -> person.name);
    comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));

    // Sort the stream:
    Stream<Person> personStream = people.stream().sorted(comparator);

    // Make sure that the output is as expected:
    List<Person> sortedPeople = personStream.collect(Collectors.toList());
    Assert.assertEquals("Andi",  sortedPeople.get(0).name); Assert.assertEquals(2,  sortedPeople.get(0).age);
    Assert.assertEquals("Barry", sortedPeople.get(1).name); Assert.assertEquals(20, sortedPeople.get(1).age);
    Assert.assertEquals("Barry", sortedPeople.get(2).name); Assert.assertEquals(50, sortedPeople.get(2).age);
    Assert.assertEquals("Bob",   sortedPeople.get(3).name); Assert.assertEquals(40, sortedPeople.get(3).age);
    Assert.assertEquals("Bob",   sortedPeople.get(4).name); Assert.assertEquals(42, sortedPeople.get(4).age);
    Assert.assertEquals("Bob",   sortedPeople.get(5).name); Assert.assertEquals(72, sortedPeople.get(5).age);
    Assert.assertEquals("Cathy", sortedPeople.get(6).name); Assert.assertEquals(40, sortedPeople.get(6).age);
    Assert.assertEquals("Dan",   sortedPeople.get(7).name); Assert.assertEquals(4,  sortedPeople.get(7).age);
    Assert.assertEquals("Debby", sortedPeople.get(8).name); Assert.assertEquals(3,  sortedPeople.get(8).age);
    // Andi     : 2
    // Barry    : 20
    // Barry    : 50
    // Bob      : 40
    // Bob      : 42
    // Bob      : 72
    // Cathy    : 40
    // Dan      : 4
    // Debby    : 3
}

/**
 * A person in our system.
 */
public static class Person
{
    /**
     * Creates a new person.
     * @param name The name of the person.
     * @param age The age of the person.
     */
    public Person(String name, int age)
    {
        this.age = age;
        this.name = name;
    }

    /**
     * The name of the person.
     */
    public String name;

    /**
     * The age of the person.
     */
    public int age;

    @Override
    public String toString()
    {
        if (name == null) return super.toString();
        else return String.format("%s : %d", this.name, this.age);
    }
}

7

এই Comparatorজাতীয় ব্যবহারের ক্ষেত্রে ম্যানুয়ালি লেখা একটি ভয়ঙ্কর সমাধান আইএমও। এই জাতীয় অ্যাডহক পদ্ধতির অনেক ত্রুটি রয়েছে:

  • কোনও কোড পুনরায় ব্যবহার নয়। লঙ্ঘন ডিআরওয়াই।
  • Boilerplate।
  • ত্রুটির সম্ভাবনা বেড়েছে।

তাহলে সমাধান কী?

প্রথমে কিছু তত্ত্ব।

আসুন আমরা "প্রকারের Aতুলনায় সমর্থন " প্রস্তাবটি বোঝাই Ord A। (প্রোগ্রামের দৃষ্টিকোণ থেকে, আপনি Ord Aদুটি বিষয় তুলনা করার জন্য যুক্তিযুক্ত একটি বিষয় হিসাবে ভাবতে পারেন AYes হ্যাঁ, ঠিক তেমন Comparator))

এখন, যদি Ord Aএবং Ord B, তবে তাদের সংমিশ্রণেরও (A, B)তুলনা সমর্থন করা উচিত। অর্থাত Ord (A, B)। যদি Ord A, Ord Bএবং Ord C, তারপর Ord (A, B, C)

আমরা এই যুক্তিটি স্বেচ্ছাচারিতায় ভদ্রতাতে প্রসারিত করতে পারি এবং বলতে পারি:

Ord A, Ord B, Ord C, ..., Ord ZOrd (A, B, C, .., Z)

এই বিবৃতি 1 কল করুন।

কম্পোজিটগুলির তুলনা যেমন আপনার প্রশ্নে বর্ণিত ঠিক তেমন কাজ করবে: প্রথম তুলনা প্রথমে চেষ্টা করা হবে, তারপরে পরেরটি, তার পরেরটি এবং আরও অনেক কিছু।

এটি আমাদের সমাধানের প্রথম অংশ। এখন দ্বিতীয় অংশ।

আপনি যদি তা জানেন Ord Aএবং কীভাবে রূপান্তর Bকরতে জানেন A(সেই রূপান্তর ফাংশনটিকে কল করুন f), তবে আপনিও তা পেতে পারেন Ord B। কিভাবে? ঠিক আছে, যখন দুটি Bউদাহরণের তুলনা করা হবে, আপনি প্রথমে সেগুলি Aব্যবহারে রূপান্তর করুন fএবং তারপরে প্রয়োগ করুন Ord A

এখানে, আমরা রূপান্তর ম্যাপ B → Aকরছি Ord A → Ord B। এটি বিপরীত ম্যাপিং হিসাবে পরিচিত (বাcomap সংক্ষেপে)

Ord A, (B → A)comap Ord B

এই বিবৃতি কল 2।


এখন এটি আপনার উদাহরণে প্রয়োগ করুন।

আপনার নামের একটি ডেটা টাইপ রয়েছে Personযা তিন প্রকারের ক্ষেত্রের সমন্বিত String

  • আমরা এটা জানি Ord String। বিবৃতি দ্বারা 1 Ord (String, String, String),।

  • আমরা সহজে থেকে একটি ফাংশন লিখতে পারেন Personকরতে (String, String, String)। (কেবলমাত্র তিনটি ক্ষেত্রটি ফিরিয়ে দিন)) যেহেতু আমরা জানি Ord (String, String, String)এবং Person → (String, String, String), বিবৃতি 2 দ্বারা, আমরা পেতে ব্যবহার comapকরতে পারি Ord Person

Qed।


আমি এই সমস্ত ধারণাটি কীভাবে বাস্তবায়ন করব?

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

কোডটি এর সাথে এইভাবে দেখবে:

Ord<Person> personOrd = 
 p3Ord(stringOrd, stringOrd, stringOrd).comap(
   new F<Person, P3<String, String, String>>() {
     public P3<String, String, String> f(Person x) {
       return p(x.getFirstName(), x.getLastname(), x.getAge());
     }
   }
 );

ব্যাখ্যা:

  • stringOrdটাইপ একটি অবজেক্ট Ord<String>। এটি আমাদের মূল "সমর্থন তুলনা" প্রস্তাবের সাথে মিলে যায়।
  • p3Ordএকটি পদ্ধতি যে লাগে Ord<A>, Ord<B>, Ord<C>, এবং আয় Ord<P3<A, B, C>>। এটি বিবৃতি 1 এর সাথে মিলে যায়। ( P3তিনটি উপাদানের সাথে পণ্যটির অর্থ দাঁড়ায় Product পণ্যটি কম্পোজিটের জন্য বীজগণিত শব্দ)
  • comapভাল অনুরূপ comap,।
  • F<A, B>একটি রূপান্তর ফাংশন প্রতিনিধিত্ব করে A → B
  • p পণ্য তৈরির জন্য একটি কারখানা পদ্ধতি।
  • পুরো প্রকাশটি বিবৃতি 2 এর সাথে মিলে যায়।

আশা করি এইটি কাজ করবে.


5

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


3

আমি মনে করি আপনার তুলনা অ্যালগরিদম "চালাক" হলে এটি আরও বিভ্রান্তিকর হবে। আপনার প্রস্তাবিত অসংখ্য তুলনা পদ্ধতির সাথে আমি যাব।

আমার জন্য একমাত্র ব্যতিক্রম হবে সমতা। ইউনিট পরীক্ষার জন্য, বেশিরভাগ ক্ষেত্র দুটি বস্তুর মধ্যে সমান কিনা (এবং উল্লেখগুলি সমান নয়) তা নির্ধারণ করার জন্য .quals (in in নেট) ওভাররাইড করা আমার পক্ষে দরকারী me


3

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


3
//Following is the example in jdk 1.8
package com;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

class User {
    private String firstName;
    private String lastName;
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public User setAge(Integer age) {
        this.age = age;
        return this;
    }

    public String getFirstName() {
        return firstName;
    }

    public User setFirstName(String firstName) {
        this.firstName = firstName;
        return this;
    }

    public String getLastName() {
        return lastName;
    }

    public User setLastName(String lastName) {
        this.lastName = lastName;
        return this;
    }

}

public class MultiFieldsComparision {

    public static void main(String[] args) {
        List<User> users = new ArrayList<User>();

        User u1 = new User().setFirstName("Pawan").setLastName("Singh").setAge(38);
        User u2 = new User().setFirstName("Pawan").setLastName("Payal").setAge(37);
        User u3 = new User().setFirstName("Anuj").setLastName("Kumar").setAge(60);
        User u4 = new User().setFirstName("Anuj").setLastName("Kumar").setAge(43);
        User u5 = new User().setFirstName("Pawan").setLastName("Chamoli").setAge(44);
        User u6 = new User().setFirstName("Pawan").setLastName("Singh").setAge(5);

        users.add(u1);
        users.add(u2);
        users.add(u3);
        users.add(u4);
        users.add(u5);
        users.add(u6);

        System.out.println("****** Before Sorting ******");

        users.forEach(user -> {
            System.out.println(user.getFirstName() + " , " + user.getLastName() + " , " + user.getAge());
        });

        System.out.println("****** Aftre Sorting ******");

        users.sort(
                Comparator.comparing(User::getFirstName).thenComparing(User::getLastName).thenComparing(User::getAge));

        users.forEach(user -> {
            System.out.println(user.getFirstName() + " , " + user.getLastName() + " , " + user.getAge());
        });

    }

}

3

যদি আমাদের একাধিক ক্ষেত্রের উপর ভিত্তি করে ব্যক্তি বস্তুটি বাছাই করতে হয় তবে কোডটির বাস্তবায়ন এখানে।

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Person {

private String firstName;
private String lastName;
private int age;

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public Person(String firstName, String lastName, int age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
}


static class PersonSortingComparator implements Comparator<Person> {

    @Override
    public int compare(Person person1, Person person2) {

        // for first name comparison
        int firstNameCompare = person1.getFirstName().compareTo(person2.getFirstName());

        // for last name comparison
        int lastNameCompare = person1.getLastName().compareTo(person2.getLastName());

        // for last name comparison
        int ageCompare = person1.getAge() - person2.getAge();

        // Now comparing
        if (firstNameCompare == 0) {
            if (lastNameCompare == 0) {
                return ageCompare;
            }
            return lastNameCompare;
        }
        return firstNameCompare;
    }
}

public static void main(String[] args) {
    Person person1 = new Person("Ajay", "Kumar", 27);
    Person person2 = new Person("Ajay","Gupta", 23);
    Person person3 = new Person("Ajay","Kumar", 22);


    ArrayList<Person> persons = new ArrayList<>();
    persons.add(person1);
    persons.add(person2);
    persons.add(person3);


    System.out.println("Before Sorting:\n");
    for (Person person : persons) {
        System.out.println(person.firstName + " " + person.lastName + " " + person.age);
    }

    Collections.sort(persons, new PersonSortingComparator());

    System.out.println("After Sorting:\n");
    for (Person person : persons) {
        System.out.println(person.firstName + " " + person.lastName + " " + person.age);
    }
}

}

2
//here threshold,buyRange,targetPercentage are three keys on that i have sorted my arraylist 
final Comparator<BasicDBObject> 

    sortOrder = new Comparator<BasicDBObject>() {
                    public int compare(BasicDBObject e1, BasicDBObject e2) {
                        int threshold = new Double(e1.getDouble("threshold"))
                        .compareTo(new Double(e2.getDouble("threshold")));
                        if (threshold != 0)
                            return threshold;

                        int buyRange = new Double(e1.getDouble("buyRange"))
                        .compareTo(new Double(e2.getDouble("buyRange")));
                        if (buyRange != 0)
                            return buyRange;

                        return (new Double(e1.getDouble("targetPercentage")) < new Double(
                                e2.getDouble("targetPercentage")) ? -1 : (new Double(
                                        e1.getDouble("targetPercentage")) == new Double(
                                                e2.getDouble("targetPercentage")) ? 0 : 1));
                    }
                };
                Collections.sort(objectList, sortOrder);

আমি এই প্রশ্নে এসেছি কারণ আমার কোডটি আপনার উত্তরটি পছন্দ করতে শুরু করেছে;)
জান গ্রোথ

0

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

এছাড়াও নোট করুন যে সাধারণত যদি a.compareTo (খ) == 0 হয় তবে a.equals (খ) == সত্য। এটি ঠিক না তবে সচেতন হতে পার্শ্ব প্রতিক্রিয়া রয়েছে। তুলনীয় ইন্টারফেসে দুর্দান্ত জাভাদোকগুলি দেখুন এবং আপনি এটিতে প্রচুর দুর্দান্ত তথ্য পাবেন।


0

নিম্নলিখিত ব্লগ দেওয়া ভাল চেইন তুলনামূলক উদাহরণ দেওয়া

http://www.codejava.net/java-core/collections/sorting-a-list-by-multiple-attributes-example

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * This is a chained comparator that is used to sort a list by multiple
 * attributes by chaining a sequence of comparators of individual fields
 * together.
 *
 */
public class EmployeeChainedComparator implements Comparator<Employee> {

    private List<Comparator<Employee>> listComparators;

    @SafeVarargs
    public EmployeeChainedComparator(Comparator<Employee>... comparators) {
        this.listComparators = Arrays.asList(comparators);
    }

    @Override
    public int compare(Employee emp1, Employee emp2) {
        for (Comparator<Employee> comparator : listComparators) {
            int result = comparator.compare(emp1, emp2);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }
}

কলকারী তুলনামূলক:

Collections.sort(listEmployees, new EmployeeChainedComparator(
                new EmployeeJobTitleComparator(),
                new EmployeeAgeComparator(),
                new EmployeeSalaryComparator())
        );


0

জাভাতে হ্যাশকোড পদ্ধতির সাথে দুটি বস্তুর তুলনা করা সহজ `

public class Sample{

  String a=null;
  String b=null;

  public Sample(){
      a="s";
      b="a";
  }
  public Sample(String a,String b){
      this.a=a;
      this.b=b;
  }
  public static void main(String args[]){
      Sample f=new Sample("b","12");
      Sample s=new Sample("b","12");
      //will return true
      System.out.println((s.a.hashCode()+s.b.hashCode())==(f.a.hashCode()+f.b.hashCode()));

      //will return false
      Sample f=new Sample("b","12");
      Sample s=new Sample("b","13");
      System.out.println((s.a.hashCode()+s.b.hashCode())==(f.a.hashCode()+f.b.hashCode()));

}

দয়া করে এটি করবেন না। হ্যাশকোডগুলি সমতার তুলনার জন্য ব্যবহার করা উচিত নয় তবে হ্যাশটেবল ইনডেক্সিংয়ের জন্য। হ্যাশের সংঘর্ষের ফলে দুটি পৃথক বস্তুর সমতা হতে পারে। এমনকি হ্যাশ টেবিলগুলি বাস্তব সমতার উপর নির্ভর করে যদি হ্যাশের সংঘর্ষ হয়।
নোয়েল উইদমার

0

সাধারণত compareTo()যখনই আমাকে মাল্টিলেভেল বাছাই করতে হয় আমি আমার পদ্ধতিটিকে এইভাবে ওভাররাইড করি ।

public int compareTo(Song o) {
    // TODO Auto-generated method stub
    int comp1 = 10000000*(movie.compareTo(o.movie))+1000*(artist.compareTo(o.artist))+songLength;
    int comp2 = 10000000*(o.movie.compareTo(movie))+1000*(o.artist.compareTo(artist))+o.songLength;
    return comp1-comp2;
} 

এখানে প্রথমে চলচ্চিত্রের নামকে পরে শিল্পীর কাছে এবং শেষ পর্যন্ত গানের লেন্থকে দেওয়া হয়। আপনাকে কেবল এটি নিশ্চিত করতে হবে যে এই গুণকগুলি একে অপরের সীমানা অতিক্রম না করার জন্য যথেষ্ট দূরের।


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