java-如何在不使用比较器和比较器接口的情况下对地图进行排序?如何编写自定义排序?

问题-我有一个学生类,它包含名称,卷号,三个主题分数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=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]

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

解决方法:

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

编辑:正如您所看到的,因为我正在使用的选择排序需要查找更大的值,所以我用大替换了lessOrEqual.效果是一样的,我这样做只是为了提高可读性.

然后,我实现了另一个静态函数,该函数接受ArrayList< Student&gt ;,对其进行排序并返回排序后的结果.所使用的排序算法非常基础:选择排序. 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)您可能会注意到,由于问题仅与排序有关,因此我没有设置任何其他变量,并且对排序唯一起作用的变量是:name和totMarks.您将不得不做剩下的事情.

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

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

    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;
    }
上一篇:如何使用forEach循环javascript对对象数组进行排序


下一篇:如何在Java中按两列对csv文件进行排序?