软件构造感想

本文档详细介绍了如何使用Java实现h-index的计算,从读取用户输入,到冒泡排序,再到计算h-index的过程。此外,还讨论了如何处理非法输入,如空数组、负值和非整数,以及如何使用Java集合类替代固定大小的数组。最后,文章提到了如何设计和编写JUnit测试用例,以及通过OOP方式改进代码结构,包括创建Paper和Author类。整个过程涵盖了代码重构和测试覆盖率的提升。
摘要由CSDN通过智能技术生成

对给定的Java项目进行实现与升级
给出一个Java题目
给定研究人员的一系列论文(每个论文是一个非负整数),编写一个函数来计算研究人员的h-index数。(
根据维奇百科上h-index的定义:“如果科学家的N篇论文中的h篇中每篇至少被引用h次,而其他N-h篇论文中每篇不超过h篇引用,则h被称为科学家的h-index。”

例子:
输入: citations = [3,0,6,1,5]
输出: 3
说明:
[3,0,6,1,5]表示研究人员总共有5篇论文,每篇论文分别获得3、0、6、1、5篇引用。 由于研究人员拥有3篇论文,每篇论文至少被3次引用,其余两篇论文每篇被引用不超过3次,因此她的h-index为3。
注意:如果h有多个可能的值,则将最大值作为h-index。
解决思路、编写Java代码、执行
思路:先把数组从大到小排序,再从头遍历,找到符合要求的h-index值。
[3,0,6,1,5]→[6,5,3,1,0]
遍历时,如果数组中该位置的数值大于等于其序号+1,则h-index至少为序号+1。
例如:

第0位为6,6>=1,则h-index=1;
第1位为5,5>=2,则h-index=2;
第2位为3,3>=3,则h-index=3;
第4位为1,1<4,则h-index不再变化,算法终止。
先创建Java项目:

在Eclipse中构造工程,命名为SC2020Spring_Classroom_Exercise;
在src中创建包,命名为exercise_6_6;
在包中创建类HIndex.java。
(1)控制台读入用户输入,按3,0,6,1,5的格式,存储于数组

Scanner scanner = new
Scanner(System.in);
int[] citations = new int[100];
String[] strs;
System.out.println("Please input the citation numbers:");
String line = scanner.nextLine();
strs = line.split(",");
for (int i = 0; i < strs.length; i++)
    citations[i] = Integer.parseInt(strs[i]);

(2)编写排序功能(冒泡排序)

for (int i = 0; i < number - 1; i++) {
    for (int j = 0; j < number - 1; j++) {
        if (citations[j] < citations[j + 1]) {
             int temp = citations[j + 1];
             citations[j + 1] = citations[j];
             citations[j] = temp;
        }
    }
}

(3)计算h-index

int hindex = 0;
for (int j = 0; j < number; j++) {
    if (citations[j] >= j + 1)
        hindex = j + 1;
    else
        break;
}
System.out.println("The h-index is: " + hindex);

接下来要输入不同的数组,进行手工测试。
上述编写完成后,git commit到v0.1All code in main()
(4)提取出单独的int hindex(int[] citations)函数
(5)提取出来形成单独的排序函数void sort(int[] array),git commit到v0.2 separate functions
(6) 从文本文件读入,存储于数组

健壮性处理
进行健壮性测试:

输入空数组——抛出异常了
String line = new String();
line = scanner.nextLine();
while(line.length() == 0)
{
    System.out.println("Input empty, please re-input:");
    line = scanner.nextLine();
}

git commit到v0.3 avoid empty input string

输入负值:
策略:split之后,调用Integer.parseInt(strs[i])得到整数,检查其是否<0
输入特殊值(非整数、非法字符等)
策略1:比较笨的方法:逐个字符位置检查是否为数字
策略2:与负值一起处理,用正则表达式检查分割后字符串是否匹配"[0-9]+"
策略3:直接调用Integer.parseInt()或者Integer.valueOf().intValue(),若抛出异常,说明不合法,需要在捕获异常之后让用户重新输入
举例实现策略2:

//read input from keyboard
Scanner scanner = new
Scanner(System.in);
System.out.println("Please input the citation numbers:");     
int[] citations = new int[100];
String[] strs;
String line = new String();     

//loop, until user inputs legal string
while (true) {
    line = scanner.nextLine();
    //if the nput is empty
    if (line.length() == 0)
    {
       System.out.println("Input empty, please re-input:");
       continue;
    }     
    //check if each part is integer >= 0
    boolean legalNumbers = true;
    strs = line.split(",");
    for (int i = 0; i < strs.length; i++) {
       //if not,stop checking others and let user re-input
       if(! strs[i].matches("[0-9]+")) {
           System.out.println(strs[i] + " is illegal: ");
           legalNumbers = false;
           break;
       }
       //otherwise,store the integer into array
       citations[i] = Integer.parseInt(strs[i]); 
    }
    if (!legalNumbers)
       continue;
    else {
       //calculate h-index
       int hindex = hindex(citations);
       //output to console
       System.out.println("The h-index is: " + hindex);
       break;
    }
}

git commit到v0.4 avoid input string containing illegal characters

需要注意的是,如果这里超过100个输入则会抛出异常,但是我们不能提前得知用户输入多少个
策略:使用Java Collections, List, Set, Map, etc
//int[] citations = new int[5];
List<Integer> citations = new ArrayList<>();
//citations[i] = value;
citations.add(value);
int hindex = hindex(citations);
public static int hindex(List<Integer> citations) {
    //Integer[]
    array1 = (Integer[])citations.toArray();
    int[] array2 = new int[citations.size()];
    for(int i=0; i<citations.size(); i++)
       array2[i] = citations.get(i);
    // 冒泡排序
    sort(array2);
    // 计算h-index
    int hindex = 0;
    for (int j = 0; j < array2.length; j++) {
       if (array2[j] >= j + 1)
           hindex = j + 1;
       else
           break;
    }
    return hindex;
}

git commit到v0.5 use java collections instead of arrays

将计算功能与用户输入分离开来
从main中分离出来计算,main只处理调用(作为客户端程序)

public class HIndex3 {    
    private List<Integer> citations = new ArrayList<>(); 
    
    public HIndex3(String input) {
       if(input == null || input.length() == 0)
           throw new IllegalArgumentException("Empty");
       dealInput(input);
    }
    
    private void dealInput(String input) {   
       String[] strs = input.split(","); 
       for (int i = 0; i < strs.length; i++) {
           if(! strs[i].matches("[0-9]+")) 
              throw new IllegalArgumentException(strs[i] + " is illegal");
           citations.add(Integer.parseInt(strs[i]));
       }
    }
    
    public static void main(String[] args) {
       String[] inputs = new String[] {"1,0", "3,-2,4,8"};
       for(int i=0;i<inputs.length;i++) {
           HIndex3 h = new HIndex3(inputs[i]);
           System.out.println(h.calcHIndex());
       }
    }
    public int calcHIndex() {...}
    ...
}

git commit到v0.6 separate input with calculation
我们还可以通过静态函数进行调用

       for(int i=0;i<inputs.length;i++) {
           //HIndex3 h = new HIndex3(inputs[i]);
           System.out.println(HIndex3.calcHIndex(inputs[i]));
       }
1
2
3
git commit到v0.7 use static methods of a class

直接编写测试用例
打开Junit,演示测试用例如何书写、如何运行、正确和错误的执行结果
创建一个新的测试类HIndexTest.java
演示如何编写测试函数并启动执行、查看结果

正确的、错误的
普通的用例如何测试:assertEquals
抛出异常如何测试?

只看抛出异常的类型是否正确
还要看抛出异常的消息是否正确
最好每个测试方法里只写一个测试用例
git commit到v0.8 design test cases manually

根据等价类和边界值思想,设计和编写测试用例
设计更完备的测试用例
Testing strategy:

对输入的字符串进行等价类划分
针对每一个划分结果来设计测试用例并撰写测试方法
git commit到v0.9 design test cases by equivalence partitioning

改造为OOP
构造Paper类,存储论文的题目、年份、期刊、引用数,封装起来,对Paper类进行功能扩展,包括增加引用数、减少引用数;
基于Paper类改造之前的HIndex类,将其改造为Author类,其中管理作者名字、发表论文清单,使用集合类表达一组Paper而不再用数组。
在Author类中增加功能:新增论文、修改某个论文的引用数、计算HIndex、toString(第一行打印出作者,后面每行是一篇论文[题目、引用数],最后是该作者的HIndex)。
写一个客户端(Author类的main函数,模拟使用Paper和Author类)

git commit到v1.0 oop

让Paper类具备在Collections中的排序功能:

方案0:自行编写排序功能
方案1:使用Comparator
方案2:使用Comparable
实现方案2
git commit到v1.1 use comparator for sorting papers

重新编写和执行JUnit测试用例
对Paper类的各函数进行测试
对Author类的各函数进行测试

构造GUI
为用户开发一个GUI,让用户输入一组论文题目和引用数,计算出HIndex
使用JFrame,创建新GUI类

读取文本文件
在GUI上选择一个文件,从文本文件里读取数据,写入Paper对象和Collections
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值