如何在不使用比较器和比较器接口的情况下对地图进行排序?如何编写自定义排序? [英] How to sort map without using comparable and Comparator Interface? How to write Custom Sorting?

查看:96
本文介绍了如何在不使用比较器和比较器接口的情况下对地图进行排序?如何编写自定义排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题-我有一个Student类,它包含名称,卷编号,三个主题分数m1,m2,m3和总分数.如果两个或两个以上学生分数相等,则需要根据学生对象的总得分对其进行排序,然后根据其名称对其进行排序. 注意-我必须在Google上进行搜索,但并没有使用Comparable和Comparator界面在每个堆栈溢出问题中获得预期的解决方案.

我创建了Studnt类

public class Student {
    private String name;
    private Integer rollNumber;
    private int m1;
    private int m2;
    private int m3;
    private int totMarks;
    //Getter setter
}

主班

public class StudentData {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enetr the number of Student");
        int totalStudent = sc.nextInt();
        Map<Integer,Student> map = new TreeMap<Integer,Student>();
        for(int i =0;i<totalStudent;i++) {
            Student ss = new Student();
            System.out.println("Enter the Student roll number");
            ss.setRollNumber(sc.nextInt());
            System.out.println("Enter the Student Name");
            ss.setName(sc.next());
            System.out.println("Enter the m1 marks ");
            ss.setM1(sc.nextInt());
            System.out.println("Enetr the m2 marks ");
            ss.setM2(sc.nextInt());
            System.out.println("Enter the m3 marks ");
            ss.setM3(sc.nextInt());
            ss.setTotMarks(ss.getM1()+ss.getM2()+ss.getM3());

            map.put(ss.getTotMarks(),ss);
            ss=null;
        }   
        //stdList.forEach(System.out::print);
        for(Map.Entry<Integer,Student> m :map.entrySet()) {
            System.out.println(m);
        }

    }
}

实际上,我正在使用TreeMap,它按键对值进行排序(总标记是我的TreeMap中的键).但是两个或两个以上的学生分数相等.然后,由于键不允许重复,较早的学生对象(值)被新学生替换了

输出

6 =学生[姓名= ved,rollNumber = 12,m1 = 2,m2 = 2,m3 = 2,totMarks = 6]

9 =学生[name = prakash,rollNumber = 56,m1 = 3,m2 = 3,m3 = 3,totMarks = 9]

地图中存储的唯一唯一的totMarks

解决方案

由于您不能使用现有的Comparator或排序算法,因此需要自己完成.我实现了static函数 lessOrEqual,该函数接受2个Student实例,对其进行比较并返回s1小于或等于s2. larger(Student s1, Student s2)返回仅当s1大于s2时才为true.可以有许多不同的方法来完成此操作,这实际上取决于您,因为这只是一个组成部分.该功能首先检查成绩,如果成绩匹配,它将检查名称并相应返回.

如您所见,我将lessOrEqual替换为larger,因为我正在使用的选择排序需要找到larger.效果是一样的,我这样做只是为了提高可读性.

然后我实现了另一个static函数,该函数接受ArrayList<Student>,对其进行排序并返回排序后的结果.所使用的排序算法非常基础:选择排序. O(N ^ 2)效率不高,但是为了简化起见,在下面的演示中我这样做了.

代码:

import java.util.ArrayList; 

public class Student {
    private String name;
    private Integer rollNumber;
    private int m1;
    private int m2;
    private int m3;
    private int totMarks;

    public static boolean larger(Student s1, Student s2){
        if(s1.totMarks < s2.totMarks) return false; 
        else if (s1.totMarks > s2.totMarks) return true;
        // compare names
        else return s1.name.compareTo(s2.name) > 0;
    }

    public static ArrayList<Student> sortSelection(ArrayList<Student> list){
        for(int i=0; i<list.size(); i++){
            for(int j=i+1; j< list.size(); j++){
                if(larger(list.get(i), list.get(j))){ // swap
                    Student temp = list.get(i); 
                    list.set(i, list.get(j));
                    list.set(j, temp);
                }
            }
        }
        return list;
    }
    //Getter setter
    public String getName(){
        return name; 
    }

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

    public int getTotMarks(){
        return totMarks;
    }

    public void setTotMarks(int totMarks){
        this.totMarks = totMarks; 
    }

    @Override
    public String toString(){
        return String.format("Name: %20s - Total Marks: %3d", name, totMarks);
    }

    public static void main(String[] args){
        Student s1 = new Student(); 
        Student s2 = new Student();
        Student s3 = new Student();
        Student s4 = new Student();

        s1.setName("John Smith");
        s1.setTotMarks(98);
        s2.setName("Jack Smith");
        s2.setTotMarks(98);
        s3.setName("Adam Noob");
        s3.setTotMarks(100);
        s4.setName("Ved Parkash");
        s4.setTotMarks(99);

        ArrayList<Student> list = new ArrayList<>(); 
        list.add(s4);
        list.add(s3);
        list.add(s1);
        list.add(s2);

        System.out.println("Array before sorting:");
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i).toString());
        }

        Student.sortSelection(list);

        System.out.println("Array after sorting:");
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i).toString());
        }
    }
}

输出:

Array before sorting:
Name:          Ved Parkash - Total Marks:  99
Name:            Adam Noob - Total Marks: 100
Name:           John Smith - Total Marks:  98
Name:           Jack Smith - Total Marks:  98
Array after sorting:
Name:           Jack Smith - Total Marks:  98
Name:           John Smith - Total Marks:  98
Name:          Ved Parkash - Total Marks:  99
Name:            Adam Noob - Total Marks: 100

注意:

1)看到将学生添加到列表中的顺序,依次为4,3,1,然后2.这是为了证明当年级匹配时,它会按名称排序(杰克·史密斯与约翰·史密斯).

2)我对学生进行了硬编码,以使其演示效果更好.

3)您可能会注意到,由于问题仅与排序有关,因此我没有设置其他任何变量,并且对排序唯一起作用的变量是:nametotMarks.您将不得不做剩下的事情.

4)我正在使用ArrayList,但这不限于此,只需简单的更改,您就可以在普通的Student[]数组上使用它.

5)函数larger不必是static,您可以使其成为成员函数并以不同的方式使用它.例如,上面的代码将更改为:

    public boolean larger(Student other){
        if(totMarks < other.totMarks) return false; 
        else if (totMarks > other.totMarks) return true;
        // compare names
        else return name.compareTo(other.name) > 0;
    }

    public static ArrayList<Student> sortSelection(ArrayList<Student> list){
        for(int i=0; i<list.size(); i++){
            for(int j=i+1; j< list.size(); j++){
                // comparison way changes accordingly
                if(list.get(i).larger(list.get(j))){ // swap
                    Student temp = list.get(i); 
                    list.set(i, list.get(j));
                    list.set(j, temp);
                }
            }
        }
        return list;
    }

Problem - I have a Student class, it contains Name, roll number, three subject marks m1,m2,m3, and total marks. I need to sort Student object according to their total marks if two or more students marks are equal then sort it according to their name. Note - I have to google it but not getting expected solution in stackoverflow question every one using Comparable and Comparator interface.

I have created class Studnt

public class Student {
    private String name;
    private Integer rollNumber;
    private int m1;
    private int m2;
    private int m3;
    private int totMarks;
    //Getter setter
}

Main class

public class StudentData {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enetr the number of Student");
        int totalStudent = sc.nextInt();
        Map<Integer,Student> map = new TreeMap<Integer,Student>();
        for(int i =0;i<totalStudent;i++) {
            Student ss = new Student();
            System.out.println("Enter the Student roll number");
            ss.setRollNumber(sc.nextInt());
            System.out.println("Enter the Student Name");
            ss.setName(sc.next());
            System.out.println("Enter the m1 marks ");
            ss.setM1(sc.nextInt());
            System.out.println("Enetr the m2 marks ");
            ss.setM2(sc.nextInt());
            System.out.println("Enter the m3 marks ");
            ss.setM3(sc.nextInt());
            ss.setTotMarks(ss.getM1()+ss.getM2()+ss.getM3());

            map.put(ss.getTotMarks(),ss);
            ss=null;
        }   
        //stdList.forEach(System.out::print);
        for(Map.Entry<Integer,Student> m :map.entrySet()) {
            System.out.println(m);
        }

    }
}

Actually, I am using TreeMap it sort the value by key(total marks is key in my TreeMap). but two or more students have equal marks. Then older student object (value) replaced by the new student because of Key not allowed duplicate

output

6=Student [name=ved, rollNumber=12, m1=2, m2=2, m3=2, totMarks=6]

9=Student [name=prakash, rollNumber=56, m1=3, m2=3, m3=3, totMarks=9]

the only unique totMarks stored in the map

解决方案

Since you can't use existing Comparator or sorting algorithms, you need to do it on your own. I have implemented a static function lessOrEqual which accepts 2 Student instances, compares them and returns whether or not s1 is less or equal to s2. larger(Student s1, Student s2) which returns true ONLY IF s1 is larger than s2. There can be many different ways of doing this, it's really up to you as it's just a comprison. The function first checks the grades, if the grades match, it will then check the name and return accordingly.

EDIT: As you can see I replaced lessOrEqual with larger since the selection sort I'm using needs to find larger. It's the same effect, I only did it for better readability of the sort.

Then I implemented another static function that accepts ArrayList<Student>, sorts it and returns it sorted. The sorting algorithm used is very basic: Selection sort. It's O(N^2) which isn't efficient, but I did it for the sake of simplicity in the demo below.

Code:

import java.util.ArrayList; 

public class Student {
    private String name;
    private Integer rollNumber;
    private int m1;
    private int m2;
    private int m3;
    private int totMarks;

    public static boolean larger(Student s1, Student s2){
        if(s1.totMarks < s2.totMarks) return false; 
        else if (s1.totMarks > s2.totMarks) return true;
        // compare names
        else return s1.name.compareTo(s2.name) > 0;
    }

    public static ArrayList<Student> sortSelection(ArrayList<Student> list){
        for(int i=0; i<list.size(); i++){
            for(int j=i+1; j< list.size(); j++){
                if(larger(list.get(i), list.get(j))){ // swap
                    Student temp = list.get(i); 
                    list.set(i, list.get(j));
                    list.set(j, temp);
                }
            }
        }
        return list;
    }
    //Getter setter
    public String getName(){
        return name; 
    }

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

    public int getTotMarks(){
        return totMarks;
    }

    public void setTotMarks(int totMarks){
        this.totMarks = totMarks; 
    }

    @Override
    public String toString(){
        return String.format("Name: %20s - Total Marks: %3d", name, totMarks);
    }

    public static void main(String[] args){
        Student s1 = new Student(); 
        Student s2 = new Student();
        Student s3 = new Student();
        Student s4 = new Student();

        s1.setName("John Smith");
        s1.setTotMarks(98);
        s2.setName("Jack Smith");
        s2.setTotMarks(98);
        s3.setName("Adam Noob");
        s3.setTotMarks(100);
        s4.setName("Ved Parkash");
        s4.setTotMarks(99);

        ArrayList<Student> list = new ArrayList<>(); 
        list.add(s4);
        list.add(s3);
        list.add(s1);
        list.add(s2);

        System.out.println("Array before sorting:");
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i).toString());
        }

        Student.sortSelection(list);

        System.out.println("Array after sorting:");
        for(int i=0; i<list.size(); i++){
            System.out.println(list.get(i).toString());
        }
    }
}

Output:

Array before sorting:
Name:          Ved Parkash - Total Marks:  99
Name:            Adam Noob - Total Marks: 100
Name:           John Smith - Total Marks:  98
Name:           Jack Smith - Total Marks:  98
Array after sorting:
Name:           Jack Smith - Total Marks:  98
Name:           John Smith - Total Marks:  98
Name:          Ved Parkash - Total Marks:  99
Name:            Adam Noob - Total Marks: 100

Notes:

1) See the order of addition of Students into the list, it's 4,3, 1 then 2. This is to prove that it sorts according to name when the grades match (Jack Smith vs John Smith).

2) I hardcoded the students to make for a better demo.

3) As you may notice, I'm not setting any of the other variables since the question is solely about sorting, and the only contributing variables to sorting are: name and totMarks. You will have to do the rest.

4) I am using ArrayList, but this isn't limited to that, with simple changes you can use it on a normal Student[] array.

5) The function larger doesn't have to be static, you can make it a member function and use it differently. For example, the code above would change to:

    public boolean larger(Student other){
        if(totMarks < other.totMarks) return false; 
        else if (totMarks > other.totMarks) return true;
        // compare names
        else return name.compareTo(other.name) > 0;
    }

    public static ArrayList<Student> sortSelection(ArrayList<Student> list){
        for(int i=0; i<list.size(); i++){
            for(int j=i+1; j< list.size(); j++){
                // comparison way changes accordingly
                if(list.get(i).larger(list.get(j))){ // swap
                    Student temp = list.get(i); 
                    list.set(i, list.get(j));
                    list.set(j, temp);
                }
            }
        }
        return list;
    }

这篇关于如何在不使用比较器和比较器接口的情况下对地图进行排序?如何编写自定义排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆