วิธีใช้ Comparator ใน Java เพื่อเรียงลำดับ


169

ฉันเรียนรู้วิธีใช้การเปรียบเทียบ แต่ฉันมีปัญหากับเครื่องมือเปรียบเทียบ ฉันมีข้อผิดพลาดในรหัสของฉัน:

Exception in thread "main" java.lang.ClassCastException: New.People cannot be cast to java.lang.Comparable
 at java.util.Arrays.mergeSort(Unknown Source)
 at java.util.Arrays.sort(Unknown Source)
 at java.util.Collections.sort(Unknown Source)
 at New.TestPeople.main(TestPeople.java:18)

นี่คือรหัสของฉัน:

import java.util.Comparator;

public class People implements Comparator {
   private int id;
   private String info;
   private double price;

   public People(int newid, String newinfo, double newprice) {
       setid(newid);
       setinfo(newinfo);
       setprice(newprice);
   }

   public int getid() {
       return id;
   }

   public void setid(int id) {
       this.id = id;
   }

   public String getinfo() {
       return info;
   }

   public void setinfo(String info) {
       this.info = info;
   }

   public double getprice() {
       return price;
   }

   public void setprice(double price) {
       this.price = price;
   }

   public int compare(Object obj1, Object obj2) {
       Integer p1 = ((People) obj1).getid();
       Integer p2 = ((People) obj2).getid();

       if (p1 > p2) {
           return 1;
       } else if (p1 < p2){
           return -1;
       } else {
           return 0;
       }
    }
}
import java.util.ArrayList;
import java.util.Collections;

public class TestPeople {
    public static void main(String[] args) {
        ArrayList peps = new ArrayList();

        peps.add(new People(123, "M", 14.25));
        peps.add(new People(234, "M", 6.21));
        peps.add(new People(362, "F", 9.23));
        peps.add(new People(111, "M", 65.99));
        peps.add(new People(535, "F", 9.23));

        Collections.sort(peps);

        for (int i = 0; i < peps.size(); i++){
            System.out.println(peps.get(i));
        }
    }
}

ฉันเชื่อว่ามันต้องทำอะไรบางอย่างกับการคัดเลือกนักแสดงในวิธีการเปรียบเทียบ แต่ฉันเล่นกับมันและยังหาวิธีแก้ปัญหาไม่ได้



1
อย่าใช้ชนิดดิบในรหัสใหม่stackoverflow.com/questions/2770321/... ; การใช้งานComparator<People>, Comparable<People>, List<People>ฯลฯ
polygenelubricants

ฉันเปลี่ยน Comparator <คน> แต่เมื่อฉันเปลี่ยน Arraylist <คน> Collections.sort จะได้รับข้อผิดพลาด
Dan

1
อ่านคำตอบของฉันเกี่ยวกับ 2 sortทับถมของ หากคุณได้รับแจ้งให้ใช้งานComparator<People>ให้ใช้ 2 ข้อโต้แย้งsortไม่ใช่ข้อโต้แย้ง 1 ข้อsort(ซึ่งต้องใช้People implements Comparable<People>)
polygenelubricants

คำตอบ:


212

มีตัวอย่างที่น่าอึดอัดใจในชั้นเรียนตัวอย่างของคุณ:

  • มันเรียกว่า People ขณะที่มีpriceและinfo (บางสิ่งบางอย่างสำหรับวัตถุมากกว่าคน);
  • เมื่อตั้งชื่อคลาสเป็นพหูพจน์ของบางสิ่งมันแสดงให้เห็นว่ามันเป็นนามธรรมมากกว่าสิ่งหนึ่ง

ต่อไปนี้เป็นตัวอย่างของวิธีใช้Comparator<T>:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, new LexicographicComparator());
        System.out.println(people);
        Collections.sort(people, new AgeComparator());
        System.out.println(people);
    }
}

class LexicographicComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.name.compareToIgnoreCase(b.name);
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }
}

class Person {

    String name;
    int age;

    Person(String n, int a) {
        name = n;
        age = a;
    }

    @Override
    public String toString() {
        return String.format("{name=%s, age=%d}", name, age);
    }
}

แก้ไข

และการสาธิต Java 8 ที่เทียบเท่าจะมีลักษณะเช่นนี้:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, (a, b) -> a.name.compareToIgnoreCase(b.name));
        System.out.println(people);
        Collections.sort(people, (a, b) -> a.age < b.age ? -1 : a.age == b.age ? 0 : 1);
        System.out.println(people);
    }
}

8
AgeComparator และการเปรียบเทียบจำนวนเต็มที่คล้ายกันสามารถทำให้ง่ายต่อการกลับมาa.age - b.age
Esko Luontola

13
@Esko: "เคล็ดลับ" การเปรียบเทียบโดยการลบถูกแบ่งสำหรับint stackoverflow.com/questions/2728793/
……

1
@Esko: เพราะสิ่งที่กล่าวถึง polygenelubricants ฉันก็ทำแบบนั้นเสมอแม้ว่าจะอายุมาก (ซึ่งจะไม่ใหญ่มาก) การลบอย่างที่คุณพูดถึงจะทำ
Bart Kiers

3
@ saikiran คุณทำได้ แต่เมื่อนำไปใช้Comparableคุณต้องเลือกแอตทริบิวต์เดียวเพื่อเปรียบเทียบ ในกรณีของบุคคลนั้นมีคุณลักษณะหลายอย่างที่เราสามารถเปรียบเทียบได้ ได้แก่ อายุความยาวเพศชื่อ ฯลฯ ในกรณีนี้คุณสามารถเปรียบเทียบคู่เปรียบเทียบที่ดำเนินการเปรียบเทียบเหล่านี้ได้อย่างง่ายดาย
Bart Kiers

1
@forsberg ไม่ไม่บังคับ แต่ขอแนะนำให้เลือก ดู: stackoverflow.com/questions/94361/…
Bart Kiers

161

นี่เป็นเทมเพลตสั้น ๆ ที่เหมาะสำหรับการจัดเรียงทันที:

Collections.sort(people,new Comparator<Person>(){
   @Override
   public int compare(final Person lhs,Person rhs) {
     //TODO return 1 if rhs should be before lhs 
     //     return -1 if lhs should be before rhs
     //     return 0 otherwise (meaning the order stays the same)
     }
 });

หากจำได้ยากลองจำไว้ว่ามันคล้ายกัน (ในแง่ของเครื่องหมายของตัวเลข) เพื่อ:

 lhs-rhs 

ในกรณีที่คุณต้องการเรียงลำดับจากน้อยไปมาก: จากจำนวนที่น้อยที่สุดไปยังจำนวนที่มากที่สุด


3
@ 40 ล็อตพวกมันใช้สำหรับวางตำแหน่งภาพไม้บรรทัดหรือแกนกับพวกมัน
ยูจีน

@android ผู้พัฒนาขอบคุณสำหรับการกล่าวถึงเคล็ดลับในการจำค่าที่จะกลับมาตามลำดับ :)
Gaur93

คำอธิบายที่ดีที่สุดcompare()ตลอดกาล
มูฮัมหมัดบาบา

นอกจากนี้ยังนำเข้า java.util.Comparator
Viraj Singh

@VirajSingh คำถามคือเกี่ยวกับชั้นนี้ดังนั้นแน่นอนมันเป็นสิ่งที่ฉันกำลังพูดถึง ...
นักพัฒนา Android

39

ใช้People implements Comparable<People>แทน สิ่งนี้กำหนดลำดับตามธรรมชาติสำหรับPeopleนี้กำหนดสั่งซื้อธรรมชาติสำหรับ

Comparator<People>ยังสามารถกำหนดนอกจากนี้ แต่People implements Comparator<People>ไม่ได้เป็นวิธีการที่เหมาะสมในการทำสิ่ง

overloads ทั้งสองCollections.sortนั้นแตกต่างกัน:

  • <T extends Comparable<? super T>> void sort(List<T> list)
    • เรียงลำดับComparableวัตถุโดยใช้การเรียงลำดับตามธรรมชาติ
  • <T> void sort(List<T> list, Comparator<? super T> c)
    • เรียงลำดับสิ่งที่ใช้งานร่วมกันได้ Comparator

คุณสับสนทั้งสองโดยพยายามเรียงลำดับComparator(ซึ่งเป็นอีกครั้งว่าทำไมมันจึงไม่สมเหตุสมผลPerson implements Comparator<Person>) หากต้องการใช้อีกครั้งCollections.sortคุณต้องมีสิ่งใดสิ่งหนึ่งต่อไปนี้ที่เป็นจริง:

  • ประเภทต้องเป็นComparable(ใช้ 1-arg sort)
  • Comparatorต้องระบุประเภทA (ใช้ 2-args sort)

คำถามที่เกี่ยวข้อง


นอกจากนี้ยังไม่ได้ใช้ประเภทดิบในรหัสใหม่ ประเภทดิบไม่ปลอดภัยและมีให้เพื่อความเข้ากันได้เท่านั้น

นั่นคือแทนที่จะเป็น:

ArrayList peps = new ArrayList(); // BAD!!! No generic safety!

คุณควรใช้การประกาศทั่วไป typesafe เช่นนี้:

List<People> peps = new ArrayList<People>(); // GOOD!!!

คุณจะพบว่ารหัสของคุณไม่ได้รวบรวมแม้แต่ !! นั่นจะเป็นสิ่งที่ดีเพราะมีบางอย่างผิดปกติกับรหัส ( Personไม่implements Comparable<Person>) แต่เนื่องจากคุณใช้ประเภทดิบคอมไพเลอร์จึงไม่ตรวจสอบสิ่งนี้และคุณจะได้รับClassCastExceptionเวลาทำงานแทน !!!

สิ่งนี้ควรโน้มน้าวให้คุณใช้ประเภททั่วไป typesafe ในรหัสใหม่ เสมอ.

ดูสิ่งนี้ด้วย


คำอธิบายของ Comparator กับ Comparable นั้นมีประโยชน์มาก
abdel

18

เพื่อความสมบูรณ์นี่เป็นวิธีการหนึ่งซับง่ายๆcompare:

Collections.sort(people, new Comparator<Person>() {
    @Override
    public int compare(Person lhs, Person rhs) {  
        return Integer.signum(lhs.getId() - rhs.getId());  
    }
});

2
ชื่นชมการใช้signum
msysmilu

1
@NumberFour "lhs.getId () - rhs.getId ()" ไม่ควรใช้มันมีการเปลี่ยนแปลงของจำนวนเต็มล้น
niraj.nijju

สำหรับสตริง "return lhs.getName () .ToTo (rhs.getName ());"
Ali Ahmed

1
Integer.compare(lhs.getId(), rhs.getId());เป็นวิธีที่ดีกว่า @ @ niraj.nijju ที่กล่าวถึงการลบอาจทำให้เกิดการล้นได้
narendra-choudhary

12

Java 8 เพิ่มวิธีการใหม่ในการทำเทียบที่ช่วยลดปริมาณของรหัสที่คุณต้องเขียนComparator.comparing ตรวจสอบComparator.reversed

นี่คือตัวอย่าง

import org.junit.Test;

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

import static org.junit.Assert.assertTrue;

public class ComparatorTest {

    @Test
    public void test() {
        List<Person> peopleList = new ArrayList<>();
        peopleList.add(new Person("A", 1000));
        peopleList.add(new Person("B", 1));
        peopleList.add(new Person("C", 50));
        peopleList.add(new Person("Z", 500));
        //sort by name, ascending
        peopleList.sort(Comparator.comparing(Person::getName));
        assertTrue(peopleList.get(0).getName().equals("A"));
        assertTrue(peopleList.get(peopleList.size() - 1).getName().equals("Z"));
        //sort by name, descending
        peopleList.sort(Comparator.comparing(Person::getName).reversed());
        assertTrue(peopleList.get(0).getName().equals("Z"));
        assertTrue(peopleList.get(peopleList.size() - 1).getName().equals("A"));
        //sort by age, ascending
        peopleList.sort(Comparator.comparing(Person::getAge));
        assertTrue(peopleList.get(0).getAge() == 1);
        assertTrue(peopleList.get(peopleList.size() - 1).getAge() == 1000);
        //sort by age, descending
        peopleList.sort(Comparator.comparing(Person::getAge).reversed());
        assertTrue(peopleList.get(0).getAge() == 1000);
        assertTrue(peopleList.get(peopleList.size() - 1).getAge() == 1);
    }

    class Person {

        String name;
        int age;

        Person(String n, int a) {
            name = n;
            age = a;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        public void setName(String name) {
            this.name = name;
        }

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



}

4

คุณต้องการใช้ Comparable ไม่ใช่ Comparator คุณต้องใช้วิธีการเปรียบเทียบกับ คุณสนิทกันมาก Comparator เป็นชุดคำสั่งเปรียบเทียบ "บุคคลที่สาม" สิ่งที่เปรียบเทียบได้คือวัตถุนี้สามารถเปรียบเทียบกับวัตถุอื่นได้

public int compareTo(Object obj1) {
  People that = (People)obj1;
  Integer p1 = this.getId();
  Integer p2 = that.getid();

  if (p1 > p2 ){
   return 1;
  }
  else if (p1 < p2){
   return -1;
  }
  else
   return 0;
 }

หมายเหตุคุณอาจต้องการตรวจสอบค่า null ในที่นี่เพื่อรับหมายเลข. เพียงแค่ในกรณี


ฉันลืมที่จะพูดถึงนี่คือการบ้านฉันได้รับคำสั่งให้ใช้เครื่องมือเปรียบเทียบ
Dan

2

นี่คือตัวอย่างของเครื่องมือเปรียบเทียบที่จะทำงานให้กับวิธีหาเรื่องศูนย์ใด ๆ ที่ส่งกลับค่าเปรียบเทียบ สิ่งนี้มีอยู่ใน jdk หรือไลบรารี่หรือไม่?

import java.lang.reflect.Method;
import java.util.Comparator;

public class NamedMethodComparator implements Comparator<Object> {

    //
    // instance variables
    //

    private String methodName;

    private boolean isAsc;

    //
    // constructor
    //

    public NamedMethodComparator(String methodName, boolean isAsc) {
        this.methodName = methodName;
        this.isAsc = isAsc;
    }

    /**
     * Method to compare two objects using the method named in the constructor.
     */
    @Override
    public int compare(Object obj1, Object obj2) {
        Comparable comp1 = getValue(obj1, methodName);
        Comparable comp2 = getValue(obj2, methodName);
        if (isAsc) {
            return comp1.compareTo(comp2);
        } else {
            return comp2.compareTo(comp1);
        }
    }

    //
    // implementation
    //

    private Comparable getValue(Object obj, String methodName) {
        Method method = getMethod(obj, methodName);
        Comparable comp = getValue(obj, method);
        return comp;
    }

    private Method getMethod(Object obj, String methodName) {
        try {
            Class[] signature = {};
            Method method = obj.getClass().getMethod(methodName, signature);
            return method;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    private Comparable getValue(Object obj, Method method) {
        Object[] args = {};
        try {
            Object rtn = method.invoke(obj, args);
            Comparable comp = (Comparable) rtn;
            return comp;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

}

มันยอดเยี่ยมจริงๆ!
Zhurov Konstantin

2

เพื่อความสมบูรณ์

ใช้ Java8

people.sort(Comparator.comparingInt(People::getId));

ถ้าคุณต้องการ descending order

people.sort(Comparator.comparingInt(People::getId).reversed());

จะเกิดอะไรขึ้นเมื่อมีวัตถุสองรายการในรายการที่มีค่าคุณสมบัติเดียวกับที่ใช้ในการเปรียบเทียบซึ่งในกรณีนี้คือPeople::getIdอะไร
Kok How Teh

คุณสามารถเพิ่มส่วน.thenComparing()คำสั่งเมื่อมีการปะทะกัน
Ankit Sharma

จะเกิดอะไรขึ้นถ้าไม่มีผลลัพธ์.thenComparing()?
Kok How Teh

จากนั้นขึ้นอยู่กับลำดับของบันทึกที่มีอยู่อ่านเพิ่มเติมเกี่ยวกับgeeksforgeeks.org/stability-in-sorting-algorithms
Ankit Sharma

ฉันจะรู้ได้อย่างไรว่าอัลกอริทึมการเรียงลำดับที่ใช้มีความเสถียรหรือไม่เสถียรหรือไม่
Kok How Teh

1
public static Comparator<JobSet> JobEndTimeComparator = new Comparator<JobSet>() {
            public int compare(JobSet j1, JobSet j2) {
                int cost1 = j1.cost;
                int cost2 = j2.cost;
                return cost1-cost2;
            }
        };

1

วิธีการแก้ปัญหาสามารถปรับให้เหมาะสมในวิธีต่อไปนี้: ประการแรกใช้คลาสส่วนตัวภายในเป็นขอบเขตสำหรับเขตข้อมูลคือการเป็น TestPeople ระดับล้อมรอบดังนั้นการใช้งานของชั้นเรียนคนจะไม่ได้สัมผัสกับโลกภายนอก สิ่งนี้สามารถเข้าใจได้ในแง่ของการสร้าง API ซึ่งคาดว่าจะมีรายชื่อของคนที่สองเรียงลำดับโดยใช้นิพจน์ Lamba (java 8) ซึ่งลดรหัสดังนั้นจึงมีความพยายามในการพัฒนา

ดังนั้นรหัสจะเป็นดังนี้:

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

public class TestPeople {
    public static void main(String[] args) {
        ArrayList<People> peps = new ArrayList<>();// Be specific, to avoid
                                                    // classCast Exception

        TestPeople test = new TestPeople();

        peps.add(test.new People(123, "M", 14.25));
        peps.add(test.new People(234, "M", 6.21));
        peps.add(test.new People(362, "F", 9.23));
        peps.add(test.new People(111, "M", 65.99));
        peps.add(test.new People(535, "F", 9.23));

        /*
         * Collections.sort(peps);
         * 
         * for (int i = 0; i < peps.size(); i++){
         * System.out.println(peps.get(i)); }
         */

        // The above code can be replaced by followin:

        peps.sort((People p1, People p2) -> p1.getid() - p2.getid());

        peps.forEach((p) -> System.out.println(" " + p.toString()));

    }

    private class People {
        private int id;

        @Override
        public String toString() {
            return "People [id=" + id + ", info=" + info + ", price=" + price + "]";
        }

        private String info;
        private double price;

        public People(int newid, String newinfo, double newprice) {
            setid(newid);
            setinfo(newinfo);
            setprice(newprice);
        }

        public int getid() {
            return id;
        }

        public void setid(int id) {
            this.id = id;
        }

        public String getinfo() {
            return info;
        }

        public void setinfo(String info) {
            this.info = info;
        }

        public double getprice() {
            return price;
        }

        public void setprice(double price) {
            this.price = price;
        }
    }
}

0

คุณควรใช้วิธีการเรียงลำดับที่มากเกินไป (peps, People ใหม่ ())

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

public class Test 
{
    public static void main(String[] args) 
    {
        List<People> peps = new ArrayList<>();

        peps.add(new People(123, "M", 14.25));
        peps.add(new People(234, "M", 6.21));
        peps.add(new People(362, "F", 9.23));
        peps.add(new People(111, "M", 65.99));
        peps.add(new People(535, "F", 9.23));

        Collections.sort(peps, new People().new ComparatorId());

        for (int i = 0; i < peps.size(); i++)
        {
            System.out.println(peps.get(i));
        }
    }
}

class People
{
       private int id;
       private String info;
       private double price;

       public People()
       {

       }

       public People(int newid, String newinfo, double newprice) {
           setid(newid);
           setinfo(newinfo);
           setprice(newprice);
       }

       public int getid() {
           return id;
       }

       public void setid(int id) {
           this.id = id;
       }

       public String getinfo() {
           return info;
       }

       public void setinfo(String info) {
           this.info = info;
       }

       public double getprice() {
           return price;
       }

       public void setprice(double price) {
           this.price = price;
       }

       class ComparatorId implements Comparator<People>
       {

        @Override
        public int compare(People obj1, People obj2) {
               Integer p1 = obj1.getid();
               Integer p2 = obj2.getid();

               if (p1 > p2) {
                   return 1;
               } else if (p1 < p2){
                   return -1;
               } else {
                   return 0;
               }
            }
       }
    }

สิ่งนี้จะใช้ได้ แต่เป็นรูปแบบที่ไม่ดี คลาสไม่ควรเป็น 'Comparator' ของมันเอง
Glorfindel

0

นี่คือคำตอบของฉันสำหรับเครื่องมือเปรียบเทียบอย่างง่าย

public class Comparator {
public boolean isComparatorRunning  = false;
public void compareTableColumns(List<String> tableNames) {
    if(!isComparatorRunning) {
        isComparatorRunning = true;
        try {
            for (String schTableName : tableNames) {
                Map<String, String> schemaTableMap = ComparatorUtil.getSchemaTableMap(schTableName); 
                Map<String, ColumnInfo> primaryColMap = ComparatorUtil.getColumnMetadataMap(DbConnectionRepository.getConnectionOne(), schemaTableMap);
                Map<String, ColumnInfo> secondaryColMap = ComparatorUtil.getColumnMetadataMap(DbConnectionRepository.getConnectionTwo(), schemaTableMap);
                ComparatorUtil.publishColumnInfoOutput("Comparing table : "+ schemaTableMap.get(CompConstants.TABLE_NAME));
                compareColumns(primaryColMap, secondaryColMap);
            }
        } catch (Exception e) {
            ComparatorUtil.publishColumnInfoOutput("ERROR"+e.getMessage());
        }
        isComparatorRunning = false;
    }
}

public void compareColumns(Map<String, ColumnInfo> primaryColMap, Map<String, ColumnInfo> secondaryColMap) {
    try {
        boolean isEqual = true;
        for(Map.Entry<String, ColumnInfo> entry : primaryColMap.entrySet()) {
            String columnName = entry.getKey();
            ColumnInfo primaryColInfo = entry.getValue();
            ColumnInfo secondaryColInfo = secondaryColMap.remove(columnName);
            if(secondaryColInfo == null) {
                // column is not present in Secondary Environment
                ComparatorUtil.publishColumnInfoOutput("ALTER", primaryColInfo);
                isEqual = false;
                continue;
            }
            if(!primaryColInfo.equals(secondaryColInfo)) {
                isEqual = false;
                // Column not equal in secondary env
                ComparatorUtil.publishColumnInfoOutput("MODIFY", primaryColInfo);
            }
        }
        if(!secondaryColMap.isEmpty()) {
            isEqual = false;
            for(Map.Entry<String, ColumnInfo> entry : secondaryColMap.entrySet()) {
                // column is not present in Primary Environment
                ComparatorUtil.publishColumnInfoOutput("DROP", entry.getValue());
            }
        }

        if(isEqual) {
            ComparatorUtil.publishColumnInfoOutput("--Exact Match");
        }
    } catch (Exception e) {
        ComparatorUtil.publishColumnInfoOutput("ERROR"+e.getMessage());
    }
}

public void compareTableColumnsValues(String primaryTableName, String primaryColumnNames, String primaryCondition, String primaryKeyColumn, 
        String secTableName, String secColumnNames, String secCondition, String secKeyColumn) {
    if(!isComparatorRunning) {
        isComparatorRunning = true;
        Connection conn1 = DbConnectionRepository.getConnectionOne();
        Connection conn2 = DbConnectionRepository.getConnectionTwo();

        String query1 = buildQuery(primaryTableName, primaryColumnNames, primaryCondition, primaryKeyColumn);
        String query2 = buildQuery(secTableName, secColumnNames, secCondition, secKeyColumn);
        try {
            Map<String,Map<String, Object>> query1Data = executeAndRefactorData(conn1, query1, primaryKeyColumn);
            Map<String,Map<String, Object>> query2Data = executeAndRefactorData(conn2, query2, secKeyColumn);

            for(Map.Entry<String,Map<String, Object>> entry : query1Data.entrySet()) {
                String key = entry.getKey();
                Map<String, Object> value = entry.getValue();
                Map<String, Object> secondaryValue = query2Data.remove(key);
                if(secondaryValue == null) {
                    ComparatorUtil.publishColumnValuesInfoOutput("NO SUCH VALUE AVAILABLE IN SECONDARY DB "+ value.toString());
                    continue;
                }
                compareMap(value, secondaryValue, key);
            }

            if(!query2Data.isEmpty()) {
                ComparatorUtil.publishColumnValuesInfoOutput("Extra Values in Secondary table "+ ((Map)query2Data.values()).values().toString());
            }
        } catch (Exception e) {
            ComparatorUtil.publishColumnValuesInfoOutput("ERROR"+e.getMessage());
        }
        isComparatorRunning = false;
    }
}

private void compareMap(Map<String, Object> primaryValues, Map<String, Object> secondaryValues, String columnIdentification) {
    for(Map.Entry<String, Object> entry : primaryValues.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        Object secValue = secondaryValues.get(key);
        if(value!=null && secValue!=null && !String.valueOf(value).equalsIgnoreCase(String.valueOf(secValue))) {
            ComparatorUtil.publishColumnValuesInfoOutput(columnIdentification+" : Secondary Table does not match value ("+ value +") for column ("+ key+")");
        }
        if(value==null && secValue!=null) {
            ComparatorUtil.publishColumnValuesInfoOutput(columnIdentification+" : Values not available in primary table for column "+ key);
        }
        if(value!=null && secValue==null) {
            ComparatorUtil.publishColumnValuesInfoOutput(columnIdentification+" : Values not available in Secondary table for column "+ key);
        }
    }
}

private String buildQuery(String tableName, String column, String condition, String keyCol) {
    if(!"*".equalsIgnoreCase(column)) {
        String[] keyColArr = keyCol.split(",");
        for(String key: keyColArr) {
            if(!column.contains(key.trim())) {
                column+=","+key.trim();
            }
        }
    }
    StringBuilder queryBuilder = new StringBuilder();
    queryBuilder.append("select "+column+" from "+ tableName);
    if(!ComparatorUtil.isNullorEmpty(condition)) {
        queryBuilder.append(" where 1=1 and "+condition);
    }
    return queryBuilder.toString();
}

private Map<String,Map<String, Object>> executeAndRefactorData(Connection connection, String query, String keyColumn) {
    Map<String,Map<String, Object>> result = new HashMap<String, Map<String,Object>>();
    try {
        PreparedStatement preparedStatement = connection.prepareStatement(query);
        ResultSet resultSet = preparedStatement.executeQuery();
        resultSet.setFetchSize(1000);
        if (resultSet != null && !resultSet.isClosed()) {
            while (resultSet.next()) {
                Map<String, Object> columnValueDetails = new HashMap<String, Object>();
                int columnCount = resultSet.getMetaData().getColumnCount();
                for (int i=1; i<=columnCount; i++) {
                    String columnName = String.valueOf(resultSet.getMetaData().getColumnName(i));
                    Object columnValue = resultSet.getObject(columnName);
                    columnValueDetails.put(columnName, columnValue);
                }
                String[] keys = keyColumn.split(",");
                String newKey = "";
                for(int j=0; j<keys.length; j++) {
                    newKey += String.valueOf(columnValueDetails.get(keys[j]));
                }
                result.put(newKey , columnValueDetails);
            }
        }

    } catch (SQLException e) {
        ComparatorUtil.publishColumnValuesInfoOutput("ERROR"+e.getMessage());
    }
    return result;
}

}

เครื่องมือ Utility สำหรับเดียวกัน

public class ComparatorUtil {

public static Map<String, String> getSchemaTableMap(String tableNameWithSchema) {
    if(isNullorEmpty(tableNameWithSchema)) {
        return null;
    }
    Map<String, String> result = new LinkedHashMap<>();
    int index = tableNameWithSchema.indexOf(".");
    String schemaName = tableNameWithSchema.substring(0, index);
    String tableName = tableNameWithSchema.substring(index+1);
    result.put(CompConstants.SCHEMA_NAME, schemaName);
    result.put(CompConstants.TABLE_NAME, tableName);
    return result;
}

public static Map<String, ColumnInfo> getColumnMetadataMap(Connection conn, Map<String, String> schemaTableMap) {
    try {
        String schemaName = schemaTableMap.get(CompConstants.SCHEMA_NAME);
        String tableName = schemaTableMap.get(CompConstants.TABLE_NAME);
        ResultSet resultSetConnOne = conn.getMetaData().getColumns(null, schemaName, tableName, null);
        Map<String, ColumnInfo> resultSetTwoColInfo = getColumnInfo(schemaName, tableName, resultSetConnOne);
        return resultSetTwoColInfo;
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

/* Number Type mapping
 * 12-----VARCHAR
 * 3-----DECIMAL
 * 93-----TIMESTAMP
 * 1111-----OTHER
*/
public static Map<String, ColumnInfo> getColumnInfo(String schemaName, String tableName, ResultSet columns) {
    try {
        Map<String, ColumnInfo> tableColumnInfo = new LinkedHashMap<String, ColumnInfo>();
        while (columns.next()) {
            ColumnInfo columnInfo = new ColumnInfo();
            columnInfo.setSchemaName(schemaName);
            columnInfo.setTableName(tableName);
            columnInfo.setColumnName(columns.getString("COLUMN_NAME"));
            columnInfo.setDatatype(columns.getString("DATA_TYPE"));
            columnInfo.setColumnsize(columns.getString("COLUMN_SIZE"));
            columnInfo.setDecimaldigits(columns.getString("DECIMAL_DIGITS"));
            columnInfo.setIsNullable(columns.getString("IS_NULLABLE"));
            tableColumnInfo.put(columnInfo.getColumnName(), columnInfo);
        }
        return tableColumnInfo;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public static boolean isNullOrEmpty(Object obj) {
    if (obj == null)
        return true;
    if (String.valueOf(obj).equalsIgnoreCase("NULL")) 
        return true;
    if (obj.toString().trim().length() == 0)
        return true;
    return false;
}



public static boolean isNullorEmpty(String str) {
    if(str == null)
        return true;
    if(str.trim().length() == 0) 
        return true;
    return false;
}

public static void publishColumnInfoOutput(String type, ColumnInfo columnInfo) {
    String str = "ALTER TABLE "+columnInfo.getSchemaName()+"."+columnInfo.getTableName();
    switch(type.toUpperCase()) {
        case "ALTER":
            if("NUMBER".equalsIgnoreCase(columnInfo.getDatatype()) || "DATE".equalsIgnoreCase(columnInfo.getDatatype())) {
                str += " ADD ("+columnInfo.getColumnName()+" "+ columnInfo.getDatatype()+");";
            } else {
                str += " ADD ("+columnInfo.getColumnName()+" "+ columnInfo.getDatatype() +"("+columnInfo.getColumnsize()+"));";
            }
            break;
        case "DROP":
            str += " DROP ("+columnInfo.getColumnName()+");";
            break;
        case "MODIFY":
            if("NUMBER".equalsIgnoreCase(columnInfo.getDatatype()) || "DATE".equalsIgnoreCase(columnInfo.getDatatype())) {
                str += " MODIFY ("+columnInfo.getColumnName()+" "+ columnInfo.getDatatype()+");";
            } else {
                str += " MODIFY ("+columnInfo.getColumnName()+" "+ columnInfo.getDatatype() +"("+columnInfo.getColumnsize()+"));";
            }
            break;
    }
    publishColumnInfoOutput(str);
}

public static Map<Integer, String> allJdbcTypeName = null;

public static Map<Integer, String> getAllJdbcTypeNames() {
    Map<Integer, String> result = new HashMap<Integer, String>();
    if(allJdbcTypeName != null)
        return allJdbcTypeName;
    try {
        for (Field field : java.sql.Types.class.getFields()) {
            result.put((Integer) field.get(null), field.getName());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return allJdbcTypeName=result;
}

public static String getStringPlaces(String[] attribs) {
    String params = "";
    for(int i=0; i<attribs.length; i++) { params += "?,"; }
    return params.substring(0, params.length()-1);
}

}

คลาสข้อมูลคอลัมน์

public class ColumnInfo {
private String schemaName;
private String tableName;
private String columnName;
private String datatype;
private String columnsize;
private String decimaldigits;
private String isNullable;

0

การแก้ไขสองรายการ:

  1. คุณจะต้องทำArrayListของPeopleวัตถุ:

    ArrayList<People> preps = new ArrayList<People>(); 
  2. หลังจากเพิ่มวัตถุลงใน preps แล้วให้ใช้:

    Collections.sort(preps, new CompareId());

รวมทั้งเพิ่ม CompareIdคลาสเป็น:

class CompareId implements Comparator {  
    public int compare(Object obj1, Object obj2) {  
        People t1 = (People)obj1;  
        People t2 = (People)obj2;  

        if (t1.marks > t2.marks)  
            return 1;   
        else  
            return -1;
    }  
}

-7

ไม่ต้องเสียเวลาในการปรับใช้ Algorithm การเรียงลำดับด้วยตัวคุณเอง แทน; ใช้

Collections.sort () เพื่อจัดเรียงข้อมูล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.