2017-04-21 75 views
1

我只是在制作一个简单的程序来根据班级中的成绩列表计算平均值。该程序以用户输入学生从班级接收到的分数为基础,对他们进行平均,并将分数放在散列图上,其中Key表示课程名称,Value表示给定的分数。然而,我遇到的问题是,每增加一个键,所有先前放置的值将被新值取代。 ,我使用的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被放到外部的时候。我想这可能是价值共享一个可变变量,但我认为只有可变键是问题?如果是这种情况,最好的解决办法是什么?

代码以供参考:

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

} 

} 
+0

'静态地图<字符串,双> gradeList =新的HashMap <>( );'表示只有一个'gradeList'。所以你再次添加相同的参考。 –

+0

你只有一个'gradeList'对象,所以所有课程都引用相同的内部地图。你需要为每个课程创建一个新的HashMap <>()。 – 4castle

+0

[HashMap存储所有键的相同值的可能重复](http://stackoverflow.com/questions/43400343/hashmap-storing-same-values-for-all-keys) –

回答

0

由于意见建议:问题来自于静态字段。其实,据我所知,静态甚至不是真正的问题。

真正的问题是你使用一个字段作为全局变量在类之间共享数据,而你不需要任何字段,只能改变你的类的api。
当然,与静态字段这样做往往产生更副作用和问题......

这里:

while ((line = br.readLine()) != null) { 
     courseInfo = line.split("\\s+"); 
     String course = courseInfo[0]; 
     Grades.loadGrade(course, courseGradeFile); 
     courseList.put(course, Grades.gradeList); 
    } 

Grades.loadGrade(course, courseGradeFile);不返回任何结果。 相反,它会改变静态字段。为什么?
加载操作应该返回一些东西。
只要做到这一点:在courseList返回Map并储存起来:

while ((line = br.readLine()) != null) { 
     courseInfo = line.split("\\s+"); 
     String course = courseInfo[0]; 
     Map<String, Double> gradesMap = Grades.loadGrade(course, courseGradeFile); 
     courseList.put(course, gradesMap); 
    } 

并以这种方式改变loadGrade()

static class Grades { 

    // remove it : static Map<String, Double> gradeList = new HashMap<>(); 
    ... 
    static Map<String, Double> loadGrade(String course, String courseGradeFile) { 
     Map<String, Double> gradeMap = new HashMap<>(); 
     ... 
     return gradeMap;  
    } 
+0

这很有趣。在这种情况下,gradeList是否全部移除?而且gradationsMap会将gradeList替换为嵌套的hashmap吗?我是编程新手,因为我正在教导我自己的一切,所以我正在努力学习尽可能多的,我可以哈哈 – June

+0

它消除了什么。 'gradeList'引用一个唯一的对象,并将其重用为两个不同的键的值。的确,gradesMap将gradeList替换为嵌套地图。但是这次只能作为局部变量。好好学习:) – davidxxx