2017-04-21 10 views
1

クラスのグレードリストから平均を計算する簡単なプログラムを作成していました。このプログラムでは、クラスから受け取った学生のスコアをユーザーが入力し、平均してハッシュマップにスコアを入れます。ここで、キーはコース名を表し、Valueは与えられたスコアを表します。しかし、私が取り組んでいる問題は、キーが1つ追加されるたびに、以前に置かれた値がすべて新しい値に置き換えられることです。私が使用 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点、2点目では80%の試験を受けました。クイズは20%、宿題は50%です。最初のラインのように、プログラム出力

{Biology={Quiz=73.33333333333333, Test=85.0, Homework=25.833333333333332}} 

これは正しいされ、プログラムが第二の行を終了したときただし、2行目の平均値は、最初のものに取って代わります。出力は

になります
{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'が1つしかないことを意味します。したがって、同じ参照を繰り返し追加しています。 –

+0

あなたは1つの '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);は何も返しません。 代わりに静的フィールドを変更します。どうして ?
読み込み操作で何かが返されるはずです。
はちょうどそれを実行します。Mapを返し、courseListに格納します。

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はすべて削除されていますか? gradesMapは、gradeListをネストされたハッシュマップとして置き換えますか?私は自分自身にすべてを教えているので、私はハハのように多くを学ぼうとしているので、プログラミングには新しいです – June

+0

何も取り除きません。 'gradeList'は1つのオブジェクトだけを参照し、それを2つの異なるキーの値として再利用します。実際、gradesMapは、gradeListを入れ子のマップとして置き換えます。しかし、今回はローカル変数としてのみ。良い学習:) – davidxxx

関連する問題