Generic class with generic arraylist - java

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.

Related

The array from another class doesn't update when scanner is used

When I try to use scanner on another class I can't update the array.
private int numClients;
private int[] clients;
These are variables from my class Rooms.
public Hotel(String name, int numRooms, int numClients){
this.name = name;
this.numRooms = numRooms;
this.numClients= numClients;
this.clients = new int[numClients];
}
Of course I added setters and getters:
public String getName() {
return name;
}
public void setNaziv(String name) {
this.name = name;
}
public int getNumRooms() {
return numRooms;
}
public void setNumRooms(int numRooms) {
this.numRooms = numRooms;
}
public int getNumClients() {
return numClients;
}
public void setNumClients(int numClients) {
this.numClients = numClients;
}
When I tried to add it to test it in another class, name and numRooms change. numClients change too but array doesn't update.
Hotel h1 = new Hotel(" ", 0, 0);
String name= sc.nextLine();
h1.setName(name);
int numRooms= sc.nextInt();
h1.setNumRooms(numRooms);
int numClients= sc.nextInt();
h1.numClients(numClients);
h1.show();
This is the show method:
public void show(){
System.out.println("Name: " + this.name);
System.out.println("Rooms: " + this.numRooms);
System.out.println("Number of clients: " + this.numClients);
for(int i = 0; i < clients.length; i++) {
System.out.println(clients[i]);
}
}
Maybe there will be some typing errors I translated the var names to English for question purposes.
Once you have created the array, it's size is fixed. You can test this with a few rows:
int size = 10; // Start with size 10
int[] array = new int[size]; // Array is 10 elements long
System.out.println(size); // Prints 10
System.out.println(array.length); // Also prints 10
size = 1000; // Change size ??
System.out.println(size); // Prints 1000
System.out.println(array.length); // Still prints 10
Output:
10
10
1000
10
You also don't appear to actually set any elements in the array in your code. That would be something like
h1.getClients()[0] = 3;
Edit
When this line in your constructor is exectuted:
this.clients = new int[numClients];
The array is created with the size that numClients has right at that moment. After that, there is no relation between numClients and clients anymore.
You would need to create a new array, copy contents (if you want to preserve it) and reassign clients with the new array in order to change the size.
You can do this with Arrays.copyOf() :
int newLength = 20;
array = Arrays.copyOf(array, newLength);
System.out.println(array.length); // Prints 20!!
The constructor will run once for a single object. So, if you want to add more values in the clients array then a method is a must.
The main Class:
class Main {
public static void main(String[] args) {
Hotel hotel = new Hotel("romeo",5,10);
hotel.addClients(6);
hotel.addClients(10);
hotel.addClients(5);
hotel.show();
}
}
The Hotel Class:
class Hotel{
private int numRooms,numClients;
private String name;
private int clients[] = new int[10];
public Hotel(String name, int numRooms, int numClients){
this.name = name;
this.numRooms = numRooms;
this.numClients= numClients;
this.clients[0] = numClients;
}
The method to add Clients in the clients array:
public void addClients(int numClients){
for(int i = 0; i < clients.length; i++){
if(clients[i] == 0){
clients[i] = numClients;
break;
}
}
}
Show method output:
Name: romeo
Rooms: 5
Number of clients: 10
10
6
10
5
The Total number of clients can be found by summation of the clients array.
To make the array dynamic, the linked list data structure can be applied.
What I did to fix this without updating and making new methods is defining values with scanner and putting it into constructor.
public void test(){
Scanner sc = new Scanner(System.in);
System.out.print("Type in the name of Hotel: ");
String name= sc.nextLine();
System.out.print("Type in number of rooms: ");
int numRooms = sc.nextInt();
System.out.print("Type in the number of clients");
int numClients= sc.nextInt();
Hotel h1 = new Hotel(name, numRooms, numClients);
h1.show();
}

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 +
'}';
}
}
}

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.

Parameters, Setters and Getters

Is there a way to pass an argument from a class into an array individually (I am not sure how to word it correctly so let me try it with an example).
Suppose I have a class named Lab and from this class there is an instance variable named grade with a getter and setter. Also, there is an array.
public class Lab {
private double grade;
private double[] array = new double[10];
public void setGrade(double grade) { //sets grades for lab reports
}
public double getGrade() {
return grade;
}
Now, from a main class called Teacher I want to call lab and pass students grades into setGrade individually and for each grade passed into the parameter I want those grades to be placed in an array so that in a later class (that I will create) I can retrieve those lab grades.
Scanner input was my first thought but I was just wondering if there is another way to do this using getters, setters, constructors, etc.
You could use an ArrayList. That way you could do the following:
private ArrayList<Double> grades = new ArrayList<>();
public void addGrade(double grade){
grades.add(grade);
}
A grade will be added to 'grades' everytime you call addGrade(double grade).
Because you want to pass a single value each time to an array, you need to keep track of where you can safely add the next value
public class Lab {
private double grade;
private double[] array = new double[10];
private int insertPoint = 0;
public void setGrade(double grade) {
if (insertPoint < array.length) {
array[insertPoint] = grade;
insertPoint++;
}
}
Now, to get a value, you'll need to know which value you want to get...
public double getGrade(int index) {
double value = 0;
if (index >= 0 && < insertPoint) {
value = array[insertPoint];
}
return value;
}
Another option might be to pass the index you want to set...
public void setGrade(int index, double grade) {
if (index >= 0 && index < array.length) {
array[index] = grade;
}
}
Or you could use variable arguments...
public void setGrade(double... grade) {
for (int index = 0; index < grade.length && index < array.length; index++) {
array[index] = grade;
}
This would allow you to pass a single value or multiple values to the same method...
Lab lab = new Lab();
lab.setGrade(1);
lab.setGrade(1, 2, 3, 4, 5);
double grades[] = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
lab.setGrabe(grades);
Just remember, in above example, each call to setGrades replaces the elements in the array (up to the number of elements you pass)
It would be simpler to use some kind of List though
If your Lab class has to hold multiple grades then it should make it clear as
public class Lab {
private double[] studentGrades;
public void setStudentGrades(double[] grades) { //sets grades for lab reports
studentGrades = grades;
}
public double[] getStudentGrades() {
return studentGrades;
}
Now, in your Teacher class you'll collect the grades in a local array and use the setter to set the values on your Lab class object as
int numOfStudents = scanner.nextInt();
double[] grades = new double[numOfStudents];
for(i = 0; i < numOfStudents; i++) {
grades[i] = scanner.nextDouble();
}
lab.setStudentGrades(grades);

How to calculate student's average grade using HashMap?

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

Categories