亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在不使用可比較和比較器接口的情況下對地圖進行排序?自定義排序怎么寫?

如何在不使用可比較和比較器接口的情況下對地圖進行排序?自定義排序怎么寫?

浮云間 2022-12-21 10:52:40
問題- 我有一個學生班,它包含姓名、學號、三個科目分數 m1、m2、m3 和總分。如果兩個或更多學生的分數相等,我需要根據他們的總分對學生對象進行排序,然后根據他們的姓名對其進行排序。注意- 我必須用谷歌搜索它,但在 stackoverflow 問題中沒有得到預期的解決方案,每個問題都使用 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 中的鍵)。但兩個或更多學生的分數相同。然后舊學生對象(值)被新學生替換,因為 Key 不允許重復輸出6=學生 [姓名=ved, rollNumber=12, m1=2, m2=2, m3=2, totMarks=6]9=學生 [姓名=prakash, rollNumber=56, m1=3, m2=3, m3=3, totMarks=9]地圖中存儲的唯一唯一 totMarks
查看完整描述

3 回答

?
UYOU

TA貢獻1878條經驗 獲得超4個贊

由于您不能使用現有的 Comparator 或排序算法,因此您需要自己完成。我已經實現了一個static函數lessOrEqual,它接受 2 個Student實例,比較它們并返回是否s1小于或等于s2。 larger(Student s1, Student s2)僅當s1大于時返回真s2??梢杂泻芏嗖煌姆椒▉碜龅竭@一點,這真的取決于你,因為它只是一個比較。該函數首先檢查成績,如果成績匹配,它將檢查姓名并相應地返回。


編輯:如您所見,我替換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。這是為了證明它在成績匹配時根據姓名排序(Jack Smith vs John Smith)。


2) 我對學生進行硬編碼以制作更好的演示。


3) 正如您可能注意到的那樣,我沒有設置任何其他變量,因為問題完全是關于排序的,唯一對排序有貢獻的變量是:name和totMarks。你將不得不做剩下的事情。


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;

    }


查看完整回答
反對 回復 2022-12-21
?
胡說叔叔

TA貢獻1804條經驗 獲得超8個贊

為了保持簡單(即 KISS 原則)并解釋我與復合鍵相關的“提示”,以下是工作示例。


解決方案的“關鍵”是讓樹自然地對數據進行排序(不是,恕我直言,通過提供手動排序來添加代碼使其變得更加復雜)。因此,學生類需要返回一個樹可以自然排序的鍵。


為了產生所需的排序結果,樹的鍵是(總分,學生姓名)。


這是修改后的 Student 類(減去 getter 和 setter,但我確實添加了一個新的構造函數以使我的生活更輕松):


public class Student {

    private String name;

    private Integer rollNumber;

    private int m1;

    private int m2;

    private int m3;

    private int totMarks;

    //Getter setter


    public Student() {


    }


    public Student(String name, Integer rollNumber, int m1, int m2, int m3) {

        this.name = name;

        this.rollNumber = rollNumber;

        this.m1 = m1;

        this.m2 = m2;

        this.m3 = m3;

        this.totMarks = m1 + m2 + m3;

    }


    public String getKey() {

//      return String.format("%d-%s", totMarks, name);          // WRONG!

        return String.format("%04d-%s", totMarks, name);        // Right

    }


    public String toString() {

        return String.format("%06d: %s - %d", rollNumber, name, totMarks);

    }


}

請注意,方法中有一行注釋掉的代碼getKey帶有注釋WRONG。這與我用個位數分數測試的暗示有關。嘗試交換兩行代碼以查看正確和錯誤的結果。


這是主要的,我刪除了所有掃描儀的東西——再次讓我的生活更輕松。希望您可以關注它并重新添加到您的掃描儀循環中。


import java.util.Arrays;

import java.util.List;

import java.util.Map;

import java.util.TreeMap;


public class StudentData {

    public static void main(String[] args) {

        // Initialise a list of students (as I don't want to rekey all the details each

        // time I run the program).

        List<Student> studentList = Arrays.asList(

                    new Student("Fred", 1, 2, 2, 2),      /* Score of 6 */

                    new Student("John", 2, 2, 3, 3),      /* Score of 8 */

                    new Student("Jane", 3, 20, 25, 30),      /* Score of 75 */

                    new Student("Julie", 4, 20, 15, 10)      /* Score of 45 */

                    // add as many new students as you like, and reorder them

                    // as much as you like to see if there is any difference in the

                    // result (there shouldn't be).

        );


            // Note the key of the tree is of type String - not Integer.

            // This is the heart of the algorithm, the tree will be "sorted"

            // on the natural key provided. This "natural key" is in fact

            // a compound key that is generated by combining the total score

            // and the student name.

        Map<String,Student> map = new TreeMap<String,Student>();

        for (Student ss : studentList) {

            map.put(ss.getKey(),ss);

        }   

        //stdList.forEach(System.out::print);

        for(Map.Entry<String,Student> m :map.entrySet()) {

            System.out.println(m);

        }

    }

}

我希望您同意這是一個更簡單的解決方案。還有一個潛在的性能優勢,因為學生在被加載到樹中時被排序(即一次)。我認為這種排序的性能是 log(n)。檢索排序可能是 n log(n) 或更糟。


查看完整回答
反對 回復 2022-12-21
?
翻過高山走不出你

TA貢獻1875條經驗 獲得超3個贊

不是將值存儲為 student,而是將它們存儲為 (name, student) 的映射,這樣當遇到具有相同標記的學生時,就會將其添加到映射中。


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, Map<String, Student>> map = new TreeMap<>();

    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());


        Integer key = ss.getTotMarks();

        if (map.get(key) == null){  // if this is a new key in the map, then create a new TreeMap and put it

            final TreeMap<String, Student> nameAndStudentMap = new TreeMap<>();

            nameAndStudentMap.put(ss.getName(), ss);

            map.put(key, nameAndStudentMap);

        }else { // if the key already existed, then get the map stored and add to it.

            map.get(key).put(ss.getName(), ss);

        }


    }

    //stdList.forEach(System.out::print);

    for(Map.Entry<Integer,Map<String, Student>> m :map.entrySet()) {

        for (Map.Entry<String, Student> nameAndStudent : m.getValue().entrySet()) {

            System.out.println(m.getKey() + " = " + nameAndStudent.getValue());

        }

    }


}


查看完整回答
反對 回復 2022-12-21
  • 3 回答
  • 0 關注
  • 148 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號