java HashMap:添加新的可变值会将所有现有值更改为该值
我只是在做一个简单的程序来计算一个班级的平均成绩。该程序将学生从一个班级收到的分数的用户输入,求平均值,并将分数放在哈希图上,其中键代表课程名称,值代表给定的分数。然而,我遇到的问题是,每次添加一个键,所有以前输入的值都会被新值替换。 我使用的HashMap是嵌套的:
Map<String, Map<String, Double>> courseList = new HashMap<>();
输入文件的格式如下
Biology Test 30 90 80 Quiz 20 50 80 90 Homework 50 5 10 20 30 40 50
Calc Test 50 100 80 Quiz 20 88 50 30 50 Homework 30 5 10 20 30
第一个单词是班级的名字。然后,列出每个作业的分数。其中,每次作业后的第一个数字代表他们在平均计算中的权重。因此,第一行列出了学生在生物学方面的成绩。他们的测试重量为30%,第一次测试得90分,第二次测试得80%。测验占20%,家庭作业占50%。对于第一行,程序输出
{Biology={Quiz=73.33333333333333, Test=85.0, Homework=25.833333333333332}}
这是正确的;然而,当程序完成第二行时,第二行的平均值将取代第一行。输出变为
{Biology={Quiz=54.5, Test=90.0, Homework=16.25}, Calc={Quiz=54.5, Test=90.0,
Homework=16.25}}
你知道这是怎么发生的吗?当我尝试调试时,它似乎发生在嵌套HashMap被放入外部HashMap的时候。我在想,这个值可能共享一个可变变量,但我认为只有可变键才是问题所在?如果是这样的话,最好的解决方法是什么
参考代码:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class GpaCalculatorTest {
private static String courseName;
static Map<String, Map<String, Double>> courseList = new HashMap<>();
static void loadCourse(String courseGradeFile) {
String[] courseInfo = null;
try (BufferedReader br = new BufferedReader(new FileReader(
courseGradeFile))) {
String line;
while ((line = br.readLine()) != null) {
courseInfo = line.split("\\s+");
String course = courseInfo[0];
Grades.loadGrade(course, courseGradeFile);
courseList.put(course, Grades.gradeList);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(courseList);
}
private static final String[] ASSIGNMENTTYPE = { "Test", "Quiz",
"Homework", "Essay", "Final_Project", "Final_Essay" };
static class Grades {
static Map<String, Double> gradeList = new HashMap<>();
static void loadGrade(String course, String courseGradeFile) {
String[] courseInfo = null;
try (BufferedReader br = new BufferedReader(new FileReader(
courseGradeFile))) {
String line;
while ((line = br.readLine()) != null) {
courseInfo = line.split("\\s+");
if (courseInfo[0].equals(course)) {
break;
}
}
} catch (FileNotFoundException e) {
System.out.println("File was not found");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < courseInfo.length; i++) {
if (Arrays.asList(ASSIGNMENTTYPE).contains(courseInfo[i])) {
double sumOfGrade = 0;
int counter = 0;
for (int j = i + 2; j < courseInfo.length; j++) {
if (Arrays.asList(ASSIGNMENTTYPE).contains(
courseInfo[j])) {
break;
} else {
sumOfGrade += Integer.parseInt(courseInfo[j]);
counter++;
}
}
double average = sumOfGrade / counter;
gradeList.put(courseInfo[i], average);
}
}
}
}
public static void main(String[] args) {
loadCourse("C:\\Users\\john\\workspace\\ideas\\src\\"
+ "gpacalculator\\course_grades");
}
}
# 1 楼答案
正如评论所说:问题来自静态场。 事实上,在我看来,静电甚至不是真正的问题
真正的问题是,使用字段作为全局变量在类之间共享数据,而不需要任何字段,只需要更改类的api
当然,用静态场做这件事通常会产生更多的副作用和问题
这里:
Grades.loadGrade(course, courseGradeFile);
不返回任何内容。 相反,它改变了静态场。为什么加载操作应该返回一些内容
只需执行:返回
Map
并将其存储在courseList
:并以这种方式改变
loadGrade()
: