How to calculate student's average grade using HashMap? - java

In the Student class, I need to add a method to put a new course into the student's course collection and a method that calculates and returns the student's average grade. I keep getting "NaN" as a result when I try to calculate the student's average grade. Would appreciate any help. Thanks.
Below is my source code for the Student class.
import java.util.HashMap;
import java.util.Set;
public class Student extends Member
{
// instance variables of class Student
private HashMap<String, Double> courses;
public Student()
{
super();
courses = new HashMap<String, Double>();
}
/**
* Constructor
* #param firstName
* #param lastName
* #param emailAddress
* #param bcitId
*/
public Student(String firstName, String lastName, String emailAddress, String bcitId)
{
super(firstName, lastName, emailAddress, bcitId);
courses = new HashMap<String, Double>();
}
public void addCourse(String course, Double grade)
{
if(!courses.isEmpty()) {
courses.put(course, grade);
}
}
public Double getAverageGrade()
{
Double averageGrade = 0.0;
int counter = 0;
if(!courses.isEmpty()){
Set<String> course = courses.keySet();
for(String grade : course){
averageGrade += courses.get(grade);
counter++;
}
}
return (averageGrade /= counter);
}
}

Your method
public void addCourse(String course, Double grade)
{
if(!courses.isEmpty()) {
courses.put(course, grade);
}
}
looks funny to me. Do you intend to only add a course if there is already at least one course in the map? This way, how will the first course enter the map?
I think you tried to check for the map to exist, but that would be done differently, namely:
if (courses == null){
...
}
About the division problem look at the other answer from Saposhiente. I would only repeat it...

int counter = 0;
return (averageGrade /= counter);
NaN indicates division by zero, among other things. Counter was never incremented because no courses were added; see luksch's answer for why. Also, since you will never reference averageGrade again, you can simply use
return averageGrade / counter;
which is slightly more efficient.

The only way it's going to return NaN is when the courses.isEmpty() returns true as the couter will not be incremented and you will divide by 0.
Also you could improve your cycle by using getValues()
public Double getAverageGrade()
{
Double averageGrade = 0.0;
int counter = 0;
if(!courses.isEmpty()){
for(Double grade : courses.getValues()){
averageGrade += grade
counter++;
}
} else {
return -1; // or some value that says that are no grades yet
}
return (averageGrade /= counter);
}

Here you go with a simple HashMap technique , refer the Below code for Caluclating
average and find the Beststudent from it,Understand it well , I might help you
Thanks...
import java.util.*;
public class QueQue {
public static float getAverage(HashMap<String, ArrayList<Integer>> hm, String name) {
ArrayList<Integer> scores;
scores = hm.get(name);
if (scores == null) {
System.out.println("NOT found");
}
int sum = 0;
for (int x : scores) {
sum += x;
}
return (float) sum / scores.size();
}
// The best students from these Key-Value Pair
public static String getBestStudent(HashMap<String, ArrayList<Integer>> hm) {
double max = 0;
String beststudent = null;
for (Map.Entry<String, ArrayList<Integer>> x : hm.entrySet()) {
String name = x.getKey();
double average = getAverage(hm, name);
if (average > max) {
max = average;
beststudent = name;
}
}
return beststudent;
}
public static void main(String[] args) {
HashMap<String, ArrayList<Integer>> hm = new HashMap<>();
hm.put("Peter", new ArrayList<>());
hm.get("Peter").add(10);
hm.get("Peter").add(10);
hm.get("Peter").add(10);
hm.put("Nancy", new ArrayList<>());
hm.get("Nancy").add(7);
hm.get("Nancy").add(8);
hm.get("Nancy").add(8);
hm.put("Lily", new ArrayList<>());
hm.get("Lily").add(9);
hm.get("Lily").add(9);
hm.get("Lily").add(8);
System.out.println("Find the average of the Peter");
float num = getAverage(hm, "Peter");
System.out.println(num);
String name = getBestStudent(hm);
System.out.println(name);
}
}

Related

2D Array, best average calculator using HashMap

Problem Statement: I have a 2D array of strings containing student names and respective marks as below
String[][] scores = {{"Bob","85"},{"Mark","100"},{"Charles","63"},{"Mark","34"}};
I want to calculate the best average among all the students available, i.e with the above input the best average should be 85.
My Attempt:
I tried to solve this using HashMap as below.
public int bestAverageCalculator(String[][] scores) {
// This HashMap maps student name to their list of scores
Map<String,List<Integer>> scoreMap = new HashMap<String,List<Integer>>();
for(String[] score:scores) {
String name = score[0];
int currentScore =Integer.parseInt(score[1]);
if(scoreMap.containsKey(name)) {
List<Integer> scoreList = scoreMap.get(name);
scoreList.add(currentScore);
scoreMap.put(name, scoreList);
}
else {
List<Integer> scoreList = new ArrayList<Integer>();
scoreList.add(currentScore);
scoreMap.put(name, scoreList);
}
}
//scoreMap will be {Charles=[63], Bob=[85], Mark=[100, 34]}
//After Map is formed i am iterating though all the values and finding the best average as below
int bestAverage = 0;
for(List<Integer> value:scoreMap.values()) {
int sum = 0;
int count = 0;
for(int i:value) {
sum+=i;
count++;
}
int average = (int)Math.floor(sum/count);
if(average>bestAverage)
bestAverage = average;
}
return bestAverage;// returns 85
}
The implementation is correct and i am getting the answer as expected, but i was told the space complexity of the program is more and it can be achieved without using the List<Integer> for marks, i am not able to understand how average can be calculated on fly without storing list of marks.
Please suggest if any other methods can solve this other than HashMap.
Any help would be appreciated.
You could store for each student a constant amount of data :
the student's name
the sum of all the student's marks
the number of the student's marks
This will make the space complexity O(m) where m is the number of unique students (instead of your O(n) where n is the number of marks).
For example, you can have a Student class with these 3 properties (and store the data in a List<Student>), or you can have a Map<String,int[]> with the key being the student's name and the value being an array of two elements containing the sum of the marks and the number of marks.
You can construct this data while iterating over the input.
Now you can compute the average for each student and find the highest average.
Well for space saving you can store two numbers per person
avgSum and count and calculate average on the end.
I have implemented #Eran 's approach based on your code with a Map<String,int[]> with
key: student's name
value: an array of two elements [the sum of the scores, the number of scores]
public int bestAverageCalculator(String[][] scores) {
// This HashMap maps student name to their total scores and count in an int array format of [totalScores, count]
Map<String,int[]> scoreMap = new HashMap<String,int[]>();
for(String[] score:scores) {
String name = score[0];
int currentScore =Integer.parseInt(score[1]);
if(scoreMap.containsKey(name)) {
int[] scoreCount = scoreMap.get(name);
scoreCount[0] += currentScore;
scoreCount[1] ++;
scoreMap.put(name, scoreCount);
}
else {
int[] scoreCount = new int[]{currentScore, 1};
scoreMap.put(name, scoreCount);
}
}
int bestAverage = 0;
for(int[] value:scoreMap.values()) {
int average = (int)Math.floor(value[0]/value[1]);
if(average>bestAverage)
bestAverage = average;
}
return bestAverage;// returns 85
}
#Eran's idea but with Student class, at least for me it's much more clear
import java.util.*;
public class Main {
static String[][] scores = {{"Bob", "85"}, {"Mark", "100"}, {"Charles", "63"}, {"Mark", "34"}};
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (String[] score : scores) {
String name = score[0];
int currentScore = Integer.parseInt(score[1]);
Student student = findStudentByName(name, students);
if (student != null) {
student.setNumberOfScores(student.getNumberOfScores() + 1);
student.setSumOfScores(student.getSumOfScores() + currentScore);
} else {
student = new Student(name, 1, currentScore);
students.add(student);
}
}
findStudentWithBestAverage(students);
}
private static void findStudentWithBestAverage(List<Student> students) {
Student bestStudent = null;
int bestAverage = 0;
for (int i = 0; i < students.size(); i++) {
if ((students.get(i).getSumOfScores() / students.get(i).getNumberOfScores()) > bestAverage) {
bestStudent = students.get(i);
bestAverage = (students.get(i).getSumOfScores() / students.get(i).getNumberOfScores());
}
}
System.out.println(bestStudent + " with average: " + bestAverage);
}
private static Student findStudentByName(String name, List<Student> students) {
for (int i = 0; i < students.size(); i++) {
if (students.get(i).getName().equals(name)) {
return students.get(i);
}
}
return null;
}
public static class Student {
private String name;
private int numberOfScores;
private int sumOfScores;
public Student(String name, int numberOfScores, int sumOfScores) {
this.name = name;
this.numberOfScores = numberOfScores;
this.sumOfScores = sumOfScores;
}
public String getName() {
return name;
}
public int getNumberOfScores() {
return numberOfScores;
}
public void setNumberOfScores(int numberOfScores) {
this.numberOfScores = numberOfScores;
}
public int getSumOfScores() {
return sumOfScores;
}
public void setSumOfScores(int sumOfScores) {
this.sumOfScores = sumOfScores;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return name.equals(student.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", numberOfScores=" + numberOfScores +
", sumOfScores=" + sumOfScores +
'}';
}
}
}

Getting Java methods from one object and a constructor from another object

I have three class Homework that has my main(...), GradeArray, which has my methods, and StudentGrade, which has my constructor.
Currently , which is clearly wrong, I have in Homework:
GradeArray grades = new GradeArray();`
In GradeArray at the top I have StudentGrade[] ArrayGrades = new StudentGrade[size]; however this method did not give me both the contructor and the methods. I know I don't need three classes for this but my professor wants three class. How do I declare an array that has attributes from two classes so that I can get the methods from GradeArray and the constructor from StudentGrade?
Thank you for you time and help.
Here is all of my code
package homework1;
public class Homework1
{
public static int pubSize;
public static String pubCourseID;
public static void makeVarsPub(int maxSize, String courseID) //this is to makes the varibles public
{
pubSize = maxSize;
pubCourseID = courseID;
}
public int giveSize()
{
return pubSize;
}
public static void main(String[] args)
{
int maxSize = 100;
String courseID = "CS116";
//this is to makes the varibles public
makeVarsPub(maxSize, courseID);
StudentGrade grades = new StudentGrade();
grades.insert("Evans", 78, courseID);
grades.insert("Smith", 77, courseID);
grades.insert("Yee", 83, courseID);
grades.insert("Adams", 63, courseID);
grades.insert("Hashimoto", 91, courseID);
grades.insert("Stimson", 89, courseID);
grades.insert("Velasquez", 72, courseID);
grades.insert("Lamarque", 74, courseID);
grades.insert("Vang", 52, courseID);
grades.insert("Creswell", 88, courseID);
// print grade summary: course ID, average, how many A, B, C, D and Fs
System.out.println(grades);
String searchKey = "Stimson"; // search for item
String found = grades.find(searchKey);
if (found != null) {
System.out.print("Found ");
System.out.print(found);
}
else
System.out.println("Can't find " + searchKey);
// Find average and standard deviation
System.out.println("Grade Average: " + grades.avg());
System.out.println("Standard dev; " + grades.std());
// Show student grades sorted by name and sorted by grade
grades.reportGrades(); // sorted by name
grades.reportGradesSorted(); // sorted by grade
System.out.println("Deleting Smith, Yee, and Creswell");
grades.delete("Smith"); // delete 3 items
grades.delete("Yee");
grades.delete("Creswell");
System.out.println(grades); // display the course summary again
}//end of Main
}//end of homework1
package homework1;
class GradeArray
{
int nElems = 0; //keeping track of the number of entires in the array.
Homework1 homework1InfoCall = new Homework1(); //this is so I can get the information I need.
int size = homework1InfoCall.giveSize();
StudentGrade[] ArrayGrades = new StudentGrade[size];
public String ToString(String name, int score, String courseID)
{
String res = "Name: " + name + "\n";
res += "Score: " + score + "\n";
res += "CourseID " + courseID + "\n";
return res;
}
public String getName(int num) //returns name based on array location.
{
return ArrayGrades[num].name;
}
public double getScore(int num) //returns score based on array location.
{
return ArrayGrades[num].score;
}
public void insert(String name, double score, String courseID) //part of the insert method is going to be
//taken from lab one and modified to fit the need.
{
if(nElems == size){
System.out.println("Array is full");
System.out.println("Please delete an Item before trying to add more");
System.out.println("");
}
else{
ArrayGrades[nElems].name = name;
ArrayGrades[nElems].score = score;
ArrayGrades[nElems].courseID = courseID;
nElems++; // increment the number of elements
};
}
public void delete(String name) //code partly taken from lab1
{
int j;
for(j=0; j<nElems; j++) // look for it
if( name == ArrayGrades[j].name)
break;
if(j>nElems) // can't find it
{
System.out.println("Item not found");
}
else // found it
{
for(int k=j; k<nElems; k++) // move higher ones down
{
boolean go = true;
if ((k+2)>size)
go = false;
if(go)
ArrayGrades[k] = ArrayGrades[k+1];
}
nElems--; // decrement size
System.out.println("success");
}
}
public String find (String name){ //code partly taken from lab1
int j;
for(j=0; j<nElems; j++) // for each element,
if(ArrayGrades[j].name == name) // found item?
break; // exit loop before end
if(j == nElems) // gone to end?
return null; // yes, can't find it
else
return ArrayGrades[j].toString();
}
public double avg() //this is to get the average
{
double total = 0;
for(int j=0; j<nElems; j++)
total += ArrayGrades[j].score;
total /= nElems;
return total;
}
public double std() //this is to get the standard deviation. Information on Standard deviation derived from
//https://stackoverflow.com/questions/18390548/how-to-calculate-standard-deviation-using-java
{
double mean = 0; //this is to hold the mean
double newSum = 0;
for(int j=0; j < ArrayGrades.length; j++) //this is to get the mean.
mean =+ ArrayGrades[j].score;
for(int i=0; i < ArrayGrades.length; i++) //this is to get the new sum.
newSum =+ (ArrayGrades[i].score - mean);
mean = newSum/ArrayGrades.length; //this is to get the final answer for the mean.
return mean;
}
public StudentGrade[] reportGrades() //this is grade sorted by name
{
int in,out;
char compair; //this is for compairsons.
StudentGrade temp; //this is to hold the orginal variable.
//for the first letter cycle
for(out=1; out<ArrayGrades.length; out++)
{
temp = ArrayGrades[out];
compair= ArrayGrades[out].name.charAt(0);
in=out;
while(in>0 && ArrayGrades[in-1].name.charAt(0) > compair)
{
ArrayGrades[in] = ArrayGrades[in-1];
in--;
}
ArrayGrades[in]=temp;
}
//this is for the second run.
for(out=1; out<ArrayGrades.length; out++)
{
temp = ArrayGrades[out];
compair= ArrayGrades[out].name.charAt(1);
in=out;
while(in>0 && ArrayGrades[in-1].name.charAt(1) > compair)
{
ArrayGrades[in] = ArrayGrades[in-1];
in--;
}
ArrayGrades[in]=temp;
}
return ArrayGrades;
}
public StudentGrade[] reportGradesSorted() //this is grades sorted by grades.
//this is grabbed from lab2 and repurposed.
{
int in,out;
double temp;
for(out=1; out<ArrayGrades.length; out++)
{
temp=ArrayGrades[out].score;
in=out;
while(in>0 && ArrayGrades[in-1].score>=temp)
{
ArrayGrades[in]= ArrayGrades[in-1];
in--;
}
ArrayGrades[in].score=temp;
}
return ArrayGrades;
} //end of GradeArray
package homework1;
public class StudentGrade extends GradeArray
{
public String name;
double score;
public String courseID;
public void StudentGrade (String name, double score, String courseID) //this is the constructor
{
this.name = name;
this.score = score;
this.courseID = courseID;
}
}//end of StudentGrade class.
First, I feel #Alexandr has the best answer. Talk with your professor.
Your question doesn't make it quite clear what you need. However, it sounds like basic understanding of inheritance and class construction would get you going on the right path. Each of the 3 classes will have a constructor that is unique to that type. Each of the 3 classes will have methods and data (members) unique to those types.
Below is just a quick example of what I threw together. I have strong concerns that my answer is actually what your professor is looking for however--it is not an object model I would suggest--just an example.
public class Homework {
private String student;
public Homework(String name) {
student = name;
}
public String getStudent() {
return student;
}
}
public class StudentGrade extends Homework {
private String grade;
public StudentGrade(String grade, String name) {
super(name);
this.grade = grade;
}
public String getGrade() {
return grade;
}
}
public class HomeworkGrades {
public List<StudentGrade> getGrades() {
// this method isnt implemented but should
// be finished to return array of grades
}
}
Take a look and see if that helps you understand something about inheritance and class construction.
Hopefully you can infer a bit about inheritence (StudentGrade inherits -- in java extends -- from HomeWork) and class construction.
Thnx
Matt
I change the array creation in Homework1 to be StudentGrade grades = new StudentGrade(); and I added extends GradeArray to the StudentGrade class. it is now public class StudentGrade extends GradeArray.

Trying to modularize methods for average, min and max

This is from a project that I recently submitted, and I'm kind of frustrated that I couldn't figure this out.
I've got an ArrayList of my objects called studentList; the Student objects' state consists of the following:
private String studentName;
private double quiz1;
private double quiz2;
private double quiz3;
private double quiz4;
private double midTermOne;
private double midTermTwo;
private double finalTest;
private String letterGrade;
I couldn't figure out how to modularize the following code in order to prevent repeating it for each column (i.e. test scores for a student):
...
double quiz1Total = 0.0;
double quiz1Avg = 0.0;
double quiz1min = studentsList.get(0).getQuiz1();
double quiz1max = studentsList.get(0).getQuiz1();
for (int i = 0; i < studentsList.size(); i++) {
quiz1Total += studentsList.get(i).getQuiz1();
if (studentsList.get(i).getQuiz1() > quiz1max) {
quiz1max = studentsList.get(i).getQuiz1();
} // if
if (studentsList.get(i).getQuiz1() < quiz1min){
quiz1min = studentsList.get(i).getQuiz1();
} // if
} // for
quiz1Avg = quiz1Total / studentsList.size();
...
Is the recommendation to extract the test scores into a temp array first and then just pass that to the average/min/max method?
I'm not having trouble with the average/min/max concepts, just the model that I should be using so that I can modularize it.
Thanks.
In Java 8 you could use a method reference or lambda.
But I would simply change the way all of your data is stored in your student class. You could use an array, but I'd use an enum:
public enum Quiz {
QUIZ_1,
QUIZ_2,
QUIZ_3,
QUIZ_4,
MID_TERM_1,
MID_TERM_2,
FINAL_TEST
}
public final class Student {
private final EnumMap<Quiz, Double> grades
= new EnumMap<>(Quiz.class);
public void setGrade(Quiz quiz, double grade) {
grades.put(quiz, grade);
}
public double getGrade(Quiz quiz) {
Double grade = grades.get(quiz);
if (grade == null) {
throw new IllegalArgumentException(
"Student has no grade yet for quiz " + quiz);
}
return grade;
}
}
static double computeAverage(List<Student> students, Quiz quiz) {
double sum = 0;
for (Student student : students) {
sum += student.getGrade(quiz);
}
return sum / students.size();
}
Update: Since you mentioned that you are using Java 8, there's an even easier way, which makes use of some advanced Java 8 features.
Assuming your Student class has methods like getQuiz1(), getQuiz2(), etc., you could do:
List<Student> students = ...
DoubleSummaryStatistics stats = students.stream()
.mapToDouble(Student::getQuiz1)
.summaryStatistics();
double quiz1average = stats.getAverage();
double quiz1max = stats.getMax();
// etc.
// And likewise for quiz2:
DoubleSummaryStatistics stats = students.stream()
.mapToDouble(Student::getQuiz2)
.summaryStatistics();
That is what structures like Arrays are good for.
Either extract the four quizes into an array or, if are allowed to, modify the student class to represent them as an Array in the first place. So your code will look something like:
for every quiz
for every student
...
Is the recommendation to extract the test scores into a temp array first and then just pass that to the average/min/max method?
Yes, you could do that. Or you could store them in arrays to begin with:
class Student {
double[] scores = new double[7];
static final int QUIZ1 = 0;
static final int QUIZ2 = 1;
...
static double average(Student[] students, int scoreIndex) {
...
for(Student student : students) {
sum += student.scores[scoreIndex];
}
...
}
}
(That might be unwieldy in practice, but probably uses concepts you are familiar with.)
Or you could use a Map:
class Student {
Map<String, Double> scores = new HashMap<>();
Student() {
scores.put("quiz1", 0);
scores.put("quiz2", 0);
...
}
static double average(Student[] students, String scoreKey) {
...
for(Student student : students) {
sum += student.scores.get(scoreKey);
}
...
}
}
Assuming quizzes are identifiable, let's say by a String name (or id, whatever), you should store their results for each student in a map:
private Map<String, Double> results = new HashMap<>();
Then add methods to student to get/set the results for a quiz:
public double getResult(String quiz) {
if (results.containsKey(quiz))
return results.get(quiz);
return 0; // hasn't done quiz, so zero score
}
public void setResult(String quiz, double result) {
results.put(quiz, result);
}
Then to calculate an average for a quiz for a some students:
public static double average(Collection<Student> students, String quiz) {
double total = 0;
for (Student student : students)
total += student.getResult(quiz);
return total / students.size();
}
You probably want to represent quiz1 quiz2 ect... as an array so something like this in your student object
class Student {
double[] myQuizs = new double[4];
public double[] getQuizScores(){
return myQuizs;
}
public double getQuiz(double num){
return myQuizs[n];
}
}
then you could do this:
double quizTotal[] = {0,0,0,0};
double quizNAvg[] = {0,0,0,0};
double quizNMin[] = new double[4];
double quizNMax[] = new double[4];
for (int n = 0; n < 4; n++){
for (int i = 0; i < studentsList.size(); i++) {
quizTotal[n] += studentsList.get(i).getQuiz1();
if (studentsList.get(i).getQuiz(n) > quizNMax[n])
quizNMax[n] = studentsList.get(i).getQuiz(n);
if (studentsList.get(i).getQuiz(n) < quizNMin[n])
quizNMin[n] = studentsList.get(i).getQuiz(n);
}
}
4 is the number of quizes i am assuming that there are. You could change that number.
You should modifie quizTotal and quizNAvg so that they have the ammount of quizes as they do elements.

Generic class with generic arraylist

Hoping I can get some help on this. I'm trying to instantiate a generic object Student with a generic arrayList as a list of grades. I can't get my Add method to work properly. I keep getting a null pointer exception- which is obvious as it is initialized to null- just not sure what is wrong with my add method. Any help would be greatly appreciated. Also, the requirements of this assignment are very strict- I have to do it this way. Thanks.
I have two classes: the first, Student:
import java.util.ArrayList;
public class Student <S>{
private String name;
private ArrayList<S> grades;
private double average;
// the constructor
public Student (String studentName, ArrayList<S> studentGrades){
name = studentName;
grades = studentGrades;
}
// get the name
public String getName() {
return name;
}
//set the name
public void setName(String name) {
this.name = name;
}
// add a grade to the array
public void addGrade(S n){
grades.add(n);
}
// return a grade from the array. This will be used for the calculation.
public S getGrade(int n){
return grades.get(n);
}
// compute the average grade for each student
public double computeAverage(){
Double sum = 0.00;
for(S grade : grades){
if (grade instanceof Double){
sum += (Double)grade;
}
if (grade instanceof Integer){
sum += (Integer)grade;
}
}
average = sum.doubleValue()/ grades.size();
return average;
}
public String toString()
{
return name + "'s average grade is " + average;
}
}
And the second, test:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
// create the studentList array
ArrayList<Student> studentList = new ArrayList<Student>();
HashMap<String, Student> studentMap = new HashMap<String, Student>();
// the values for math.random to create the grades
int min = 0;
int max = 100;
double dmin = 0.00;
double dmax = 100.00;
// initialize the variables
ArrayList grades = null;
//------------------------------------
// Create the students (the method signature is wrong. It blows up regardless of what I try to add.)
Student<Integer> Fred = new Student<Integer>("Fred", grades);
//null pointer exception. Also points to the add method in the student class.
//-------------------------------------
Student<Integer> Wilma = new Student<Integer>("Wilma", grades);
Student<Double> Barney = new Student<Double>("Barney", grades);
Student<Double> Betty = new Student<Double>("Betty", grades);
// add the random grades
for(int i = 0; i < 5; i++){
Fred.addGrade((int) (Math.random() * (max - min) + min));
}
for(int i = 0; i < 5; i++){
Wilma.addGrade((int) (Math.random() * (max - min) + min));
}
for(int i = 0; i < 5; i++){
Barney.addGrade((double) (Math.random() * (dmax - dmin) + dmin));
}
for(int i = 0; i < 5; i++){
Betty.addGrade((double) (Math.random() * (dmax - dmin) + dmin));
}
// add the students to the array list
studentList.add(Fred);
studentList.add(Wilma);
studentList.add(Barney);
studentList.add(Betty);
studentMap.put(Fred.getName(), Fred);
studentMap.put(Wilma.getName(), Wilma);
studentMap.put(Barney.getName(), Barney);
studentMap.put(Betty.getName(), Betty);
//iterate through the list & print to the console
Iterator<Student> itr = studentList.iterator();{
while(itr.hasNext()){
System.out.println(itr.next().<Student>toString());
//Initialize the array to hold the key variables
Set<String> mapKeys = studentMap.keySet();
//mapKeys.add(something);
}
}
}
}
You need to initialize the ArrayList grades. Currently you are passing a null value. Do the following in that line:
ArrayList grades = new ArrayList();
A good practice would be to use generics while initializing the ArrayList but since your grades seem to be of differing types, I'm skipping it out.
You are initializing on Test the Grades as null
ArrayList grades = null;
and when you try to add a grade with
Fred.addGrade(...);
the internal code in Student does
grades.add(n);
But grades is initialized to null creating a Null Exception.
Initialize the grades with the proper type.
Example:
Student<Integer> Wilma = new Student<Integer>("Wilma", new ArrayList<Integer>());
Student<Double> Barney = new Student<Double>("Barney", new ArrayList<Double>());
Student<Double> Betty = new Student<Double>("Betty", new ArrayList<Double>());
In your Test class you have
ArrayList grades = null; - you need to create the grades ArrayList and fill it with data before using it.
You could do something like this:
public class Student<S>
{
// declare array
private final ArrayList<S> grades = new ArrayList<S>();
private String name;
// One arg constructor
public Student(String name)
{
this.name = name;
}
// Two arg constructor
public Student(String name, ArrayList<S> grades)
{
this(name);
this.grades.addAll(grades);
}
// etc
}
Edit your code in the following manner in Test class:
Student<Integer> Fred = new Student<Integer>("Fred", new ArrayList<Integer>());
//null pointer exception. Also points to the add method in the student class.
//-------------------------------------
Student<Integer> Wilma = new Student<Integer>("Wilma", new ArrayList<Integer>());
Student<Double> Barney = new Student<Double>("Barney", new ArrayList<Double>());
Student<Double> Betty = new Student<Double>("Betty", new ArrayList<Double>());
Hope, this will help.

java hashmap values

My hashmap contains a key which is the customers name, and the values are all the ratings for the books rated. I have to calculate the average rating for a given booktitle.
How do I access all of the values (ratings) from the hashmap? Is there a method for doing this?
Here is a piece of my code:
/**
* calculate the average rating by all customers for a named book
* only count positive or negative ratings, not 0 (unrated)
* if the booktitle is not found or their are no ratings then
* return NO_AVERAGE
* #param booktitle String to be rated
* #return double the average of all ratings for this book
*/
public double averageRating(String booktitle)
{
numberOfRatingsPerCustomer/total
}
You need to get the keySet from the HashMap. And then Iterate over the keySet and fetch the values from the HashMap.
Your question makes no sense.
You can't have a map with customerName to hisRatingOfBook, and search in it for bookTitle. You need to go one of 1 ways:
1)
create method public double averageRating() inside Book class, and keep there, as field, rating being map with customerName to hisRatingOfBook
2) Use your method:
public double averageRating(String booktitle)
{
numberOfRatingsPerCustomer/total
}
but make your map something more complex, that will hold customer, and its rating (being made from book title + rate)
Here you go take these below code it will help you out to find your rating problem
I have done to find average of Student marks in a class
import java.util.*;
public class QueQue {
public static float getAverage(HashMap<String, ArrayList<Integer>> hm, String name) {
ArrayList<Integer> scores;
scores = hm.get(name);
if (scores == null) {
System.out.println("NOT found");
}
int sum = 0;
for (int x : scores) {
sum += x;
}
return (float) sum / scores.size();
}
public static void main(String[] args) {
HashMap<String, ArrayList<Integer>> hm = new HashMap<>();
hm.put("Peter", new ArrayList<>());
hm.get("Peter").add(10);
hm.get("Peter").add(10);
hm.get("Peter").add(10);
hm.put("Nancy", new ArrayList<>());
hm.get("Nancy").add(7);
hm.get("Nancy").add(8);
hm.get("Nancy").add(8);
hm.put("Lily", new ArrayList<>());
hm.get("Lily").add(9);
hm.get("Lily").add(9);
hm.get("Lily").add(8);
System.out.println("Find the average of the Peter");
float num = getAverage(hm, "Peter");
}
}

Categories