(转)记一篇机试题

前言

最近看到一篇内容记一篇机试题:原文地址

当时评论了一句,你这么写我一定给零分。由于最近比较忙,一直没有给作者一个答复,今天稍微有点空,算是给稍微普及一下面向对象的思想吧。想想当初自己写码代码也是如此码过来的,不经唏嘘。

原文简要介绍

题目

/**
 * 1 输出每个人的名字及其平均成绩
 * 2 以平均成绩的升序排序
 * 3 有良好的命名和注释
 * 4 要体现面向对象以及代码的可复用性
 *
 * 输出结果
 * 王五 40
 * 张三 70
 * 李四 75
 */
public class jh {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(new String[]{"1,张三,90","2,李四,70","3,王五,40","4,张三,50","5,李四,80"});
    }
}

原作者解决方案

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * 1 输出每个人的名字及其平均成绩
 * 2 以平均成绩的升序排序
 * 3 有良好的命名和注释
 * 4 要体现面向对象以及代码的可复用性
 * 
 * 输出结果
 * 王五 40
 * 张三 70
 * 李四 75
 *
 * 我解题的思路:
 * 首先把字符串拆分,将名字、分数各自放到一个list集合
 * 然后用for循环比较,名字相同的,其分数相加  --> 存储的顺序一样即两个list的index对应关系一样
 * --|  后面可能有重复的名字的处理:将循环到的数据用一个for循环与前面的相比较,如果有相同的,continue到最外层的for循环,否则执行下面操作
 * --|  如果没有与前面相同的,内嵌一个for循环,与后面的名字相比较,如果相同,将对应的分数相加
 * --|  将名字与平均分数封装到Student对象中,将Student对象放到一个list集合
 * --|  将Student的list集合使用冒泡排序算法排序
 * --|  遍历Student的list集合,按顺序输出结果
 */
public class jh {
    public static void main(String[] args) {
        //原题
        List<String> list = Arrays.asList(new String[]{"1,张三,90", "2,李四,70", "3,王五,40", "4,张三,50", "5,李四,80"});
//        List<String> list = new ArrayList<>();
//        Scanner scanner = new Scanner(System.in);
//        System.out.println("请输入学生的信息(序号,名字,分数)标点符号用中文,*号退出:");
//
//        while (scanner.hasNext()){
//            String student = scanner.next();
//            if (student.equals("*")) {
//                break;
//            }
//            list.add(student);
//            System.out.println("请输入学生的信息(序号,名字,分数)标点符号用中文,*号退出:");
//        }
        //用于存放名字
        List<String> nameList = new ArrayList<String>();
        //用于存放成绩
        List<Integer> gradeList = new ArrayList<>();
        //用于存放Student对象
        List<Student> studentList = new ArrayList<>();

        //遍历题目的list
        for (String student : list) {

            //按“,”分割字符串,返回一个数组
            String[] msg = student.split(",");
            //将名字存放到list中
            nameList.add(msg[1]);
            //将分数存放到list中
            gradeList.add(Integer.parseInt(msg[2]));
        }
        outer:
        for (int i = 0; i < nameList.size(); i++) {
            //用于记录总分数
            int grade = gradeList.get(i);
            //用于记录共加了多少个人的分数
            int count = 1;
            //如果当前的名字与前面的相同,跳出循环
            for (int y = 0; y < i; y++) {
                if (nameList.get(i).equals(nameList.get(y))) {
                    continue outer;
                }
            }
            //若没有跳出循环则执行下面的for循环,将后面的与当前名字相同的分数相加,记录到grade总分数中
            for (int j = i + 1; j < nameList.size(); j++) {
                if (nameList.get(i).equals(nameList.get(j))) {
                    grade += gradeList.get(j);
                    count++;
                }
            }
            //创建一个Student对象,存放名字和平均分
            Student student = new Student();
            student.setName(nameList.get(i));
            student.setAvg(grade / count);
            //将Student对象放到list集合中
            studentList.add(student);
        }
//        System.out.println(studentList);

        //冒泡排序,升序
        for (int i = 0; i < studentList.size(); i++) {

            for (int j = i + 1; j < studentList.size(); j++) {
                if (studentList.get(i).getAvg() > studentList.get(j).getAvg()) {
                    Student s = studentList.get(i);
                    studentList.set(i, studentList.get(j));
                    studentList.set(j, s);
                }
            }
        }
//        System.out.println(studentList);
        //遍历输出结果
        for (Student student : studentList) {
            System.out.println(student.getName() + "  " + student.getAvg());
        }
    }
}

简单点评

丝毫没有面向对象的概念,JAVA的优势全丢了,没有一点可取之处。机试的目的并不是实现功能,而是看你的代码结构和编码能力还有那么一点点习惯。

改造后的代码

学生类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Student {

    private String name;
}

成绩记录单类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ScopeRecode {
    /**
     * 学生
     */
    private Student student;

    /**
     * 分数
     */
    private Integer scope;

    /**
     * 将字符串数据转换为成绩记录
     * @param data "1,张三,90" 参考格式
     * @return 成绩记录
     */
    public static ScopeRecode ofStringData(String data){
        if(!data.contains(","))return null;
        String[] datas = data.split(",");
        Student student = Student.builder().name(datas[1]).build();
        return ScopeRecode.builder().student(student).scope(Integer.valueOf(datas[2])).build();
    }

}

成绩管理类

public class ScopeManager {

    private Map<Student, List<ScopeRecode>> studentScopeRecord;

    ScopeManager(){
        studentScopeRecord =  new HashMap<>();
    }

    public void record(ScopeRecode scopeRecode){
        Student student = scopeRecode.getStudent();
        studentScopeRecord.computeIfAbsent(student, k -> new ArrayList<>());
        List<ScopeRecode> scopeRecodes = studentScopeRecord.get(student);
        scopeRecodes.add(scopeRecode);
    }

    public void recordBach(List<ScopeRecode> scopeRecodeList){
        scopeRecodeList.forEach(this::record);
    }

    /**
     * 获取按平均成绩排序后的结果
     * @return
     */
    public List<Map.Entry<Student, Integer>> getAverageScoreStatisticsOrderByScore(){
        Map<Student, Integer> averageScoreStatistics = getAverageScoreStatistics();
        //按照value排序
        List<Map.Entry<Student, Integer>> entryArrayList = new ArrayList<>(averageScoreStatistics.entrySet());
        entryArrayList.sort(Comparator.comparingInt(Map.Entry::getValue));
        return entryArrayList;

    }

    /**
     * 获取统计的平均成绩
     * @return
     */
    private Map<Student,Integer> getAverageScoreStatistics(){
        Set<Student> students = studentScopeRecord.keySet();
        Map<Student,Integer> dataMap = new HashMap<>();
        students.forEach(temp -> {
            dataMap.put(temp, getAverageScope(temp));
        });
        return dataMap;
    }

    /**
     * 获取某个学生的平均成绩
     * @param student
     * @return
     */
    private Integer getAverageScope(Student student){
        List<ScopeRecode> scopeRecodes = studentScopeRecord.get(student);
        if(scopeRecodes == null){
            return null;
        }else{
            Integer sumScope = 0;
            int num = scopeRecodes.size();
            for(ScopeRecode scopeRecode : scopeRecodes){
                sumScope += scopeRecode.getScope();
            }
            return sumScope / num;
        }
    }
}

调用类(此类名为和原文保持一致,未修正类名首字符大写的问题)

public class jh {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(new String[]{"1,张三,90","2,李四,70","3,王五,40","4,张三,50","5,李四,80"});

        List<ScopeRecode> scopeRecodeList = new ArrayList<>();
        list.forEach(temp -> scopeRecodeList.add(ScopeRecode.ofStringData(temp)));

        ScopeManager scopeManager = new ScopeManager();
        scopeManager.recordBach(scopeRecodeList);

        List<Map.Entry<Student, Integer>> averageScoreStatisticsOrderByScore = scopeManager.getAverageScoreStatisticsOrderByScore();
        for(Map.Entry<Student,Integer> entry : averageScoreStatisticsOrderByScore){
            System.out.println(entry.getKey().getName() +" " + entry.getValue());
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值