Your way
Using your code, presumably each of your three grades by position represent three different courses. I assume you put all the grades for "French" class in grade1 field, grades for "Composition" class in grade2 field, and grades for "Math" class in grade3.
So loop the students, pulling each grade separately.
float frenchPoints = 0 ;
float compositionPoints = 0 ;
float mathPoints = 0 ;
for( Student student : students )
{
frenchPoints = ( frenchPoints + student.getGrade1() ) ;
compositionPoints = ( compositionPoints + student.getGrade2() ) ;
mathPoints = ( mathPoints + student.getGrade3() ) ;
}
Divide points by the number of grades to render an average.
Do not divide a float (fractional number) by an int (integer) if you want a float result. So we must cast our int to a float before doing the division.
float frenchAverage = ( frenchPoints / (float) students.size() ) ;
…
My way
As suggested in the Answer by Bruno Souza Picinini, in a more realistic scenario, you would break out the data into separate classes. Likely you would represent Student in a class, which in turn might contain a collection of objects of a CourseGrade class.
In Java 16 we can use the new records feature to briefly write a class whose main purpose is to transparently and immutably communicate data. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.
public record CourseGrade(String courseName , YearMonth term , Float grade) {}
public record Student(UUID id , String name , Set < CourseGrade > courseGrades) {}
Let's get some example data.
private List < Student > fetchStudents ( )
{
List < Student > students =
List.of(
new Student( UUID.fromString( "57ce6790-5094-480c-88f5-79ee9e59b9bb" ) , "Alice" ,
Set.of(
new CourseGrade( "French" , YearMonth.of( 2021 , Month.JANUARY ) , 3.2F ) ,
new CourseGrade( "French" , YearMonth.of( 2021 , Month.APRIL ) , 3.6F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.JANUARY ) , 3.3F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.APRIL ) , 3.7F )
)
) ,
new Student( UUID.fromString( "3ed40f58-fb82-44f0-9ae8-7cc1b317085e" ) , "Bob" ,
Set.of(
new CourseGrade( "French" , YearMonth.of( 2021 , Month.JANUARY ) , 2.7F ) ,
new CourseGrade( "French" , YearMonth.of( 2021 , Month.APRIL ) , 2.6F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.JANUARY ) , 2.9F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.APRIL ) , 2.7F )
)
) ,
new Student( UUID.fromString( "9058567e-8a5e-4606-81b0-1def2bb8ceb5" ) , "Carol" ,
Set.of(
new CourseGrade( "French" , YearMonth.of( 2021 , Month.JANUARY ) , 3.0F ) ,
new CourseGrade( "French" , YearMonth.of( 2021 , Month.APRIL ) , 3.1F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.JANUARY ) , 3.2F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.APRIL ) , 3.4F )
)
)
);
return students;
}
Write a method to report the average grade for a particular course name for a particular term.
We report an Optional because it is possible we might be asking for a course in a term when no such class offering was made. So if no class, then no students earned any grades. So rather than report a number we want to report an empty Optional object. If a course was offered in that term with students enrolled, then we return an Optional containing a Float object for the number of the average grade.
By the way, be aware that floating-point types such as float/Float trade away inaccuracy for speed of execution. If you care about accuracy, use BigDecimal class instead.
private Optional < Float > reportAverageGradePerCourseInTerm ( String courseName , YearMonth term )
{
Objects.requireNonNull( courseName );
Objects.requireNonNull( term );
List < CourseGrade > courseGrades = new ArrayList <>( this.students.size() );
for ( Student student : this.students )
{
for ( CourseGrade courseGrade : student.courseGrades() )
{
if ( courseGrade.courseName().equals( courseName ) && courseGrade.term().equals( term ) )
{
courseGrades.add( courseGrade ); // If a match on name and term, remember this `CourseGrade` object. Else, forget/skip.
}
}
}
if ( courseGrades.size() == 0 ) { return Optional.empty(); }
float totalPoints = 0F;
for ( CourseGrade courseGrade : courseGrades )
{
totalPoints = totalPoints + courseGrade.grade();
}
Float average = ( totalPoints / ( float ) courseGrades.size() );
return Optional.of( average );
}
Pull all that code into a class App with a main method to drive a demonstration.
package work.basil.example.reportcard;
import java.time.Month;
import java.time.YearMonth;
import java.util.*;
public class App
{
public static void main ( String[] args )
{
App app = new App();
app.students = app.fetchStudents();
System.out.println( "app.students = " + app.students );
Optional < Float > averageForFrenchIn2021_01 = app.reportAverageGradePerCourseInTerm( "French" , YearMonth.of( 2021 , Month.JANUARY ) );
System.out.println( "averageForFrenchIn2021_01 = " + averageForFrenchIn2021_01 );
}
// Member fields
List < Student > students;
// Logic
private List < Student > fetchStudents ( )
{
List < Student > students =
List.of(
new Student( UUID.fromString( "57ce6790-5094-480c-88f5-79ee9e59b9bb" ) , "Alice" ,
Set.of(
new CourseGrade( "French" , YearMonth.of( 2021 , Month.JANUARY ) , 3.2F ) ,
new CourseGrade( "French" , YearMonth.of( 2021 , Month.APRIL ) , 3.6F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.JANUARY ) , 3.3F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.APRIL ) , 3.7F )
)
) ,
new Student( UUID.fromString( "57ce6790-5094-480c-88f5-79ee9e59b9bb" ) , "Bob" ,
Set.of(
new CourseGrade( "French" , YearMonth.of( 2021 , Month.JANUARY ) , 2.7F ) ,
new CourseGrade( "French" , YearMonth.of( 2021 , Month.APRIL ) , 2.6F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.JANUARY ) , 2.9F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.APRIL ) , 2.7F )
)
) ,
new Student( UUID.fromString( "57ce6790-5094-480c-88f5-79ee9e59b9bb" ) , "Carol" ,
Set.of(
new CourseGrade( "French" , YearMonth.of( 2021 , Month.JANUARY ) , 3.0F ) ,
new CourseGrade( "French" , YearMonth.of( 2021 , Month.APRIL ) , 3.1F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.JANUARY ) , 3.2F ) ,
new CourseGrade( "Composition" , YearMonth.of( 2021 , Month.APRIL ) , 3.4F )
)
)
);
return students;
}
private Optional < Float > reportAverageGradePerCourseInTerm ( String courseName , YearMonth term )
{
Objects.requireNonNull( courseName );
Objects.requireNonNull( term );
List < CourseGrade > courseGrades = new ArrayList <>( this.students.size() );
for ( Student student : this.students )
{
for ( CourseGrade courseGrade : student.courseGrades() )
{
if ( courseGrade.courseName().equals( courseName ) && courseGrade.term().equals( term ) )
{
courseGrades.add( courseGrade ); // If a match on name and term, remember this `CourseGrade` object. Else, forget/skip.
}
}
}
if ( courseGrades.size() == 0 ) { return Optional.empty(); }
float totalPoints = 0F;
for ( CourseGrade courseGrade : courseGrades )
{
totalPoints = totalPoints + courseGrade.grade();
}
Float average = ( totalPoints / ( float ) courseGrades.size() );
return Optional.of( average );
}
}
When main is run.
app.students = [Student[id=57ce6790-5094-480c-88f5-79ee9e59b9bb, name=Alice, courseGrades=[CourseGrade[courseName=French, term=2021-04, grade=3.6], CourseGrade[courseName=French, term=2021-01, grade=3.2], CourseGrade[courseName=Composition, term=2021-01, grade=3.3], CourseGrade[courseName=Composition, term=2021-04, grade=3.7]]], Student[id=57ce6790-5094-480c-88f5-79ee9e59b9bb, name=Bob, courseGrades=[CourseGrade[courseName=French, term=2021-04, grade=2.6], CourseGrade[courseName=French, term=2021-01, grade=2.7], CourseGrade[courseName=Composition, term=2021-01, grade=2.9], CourseGrade[courseName=Composition, term=2021-04, grade=2.7]]], Student[id=57ce6790-5094-480c-88f5-79ee9e59b9bb, name=Carol, courseGrades=[CourseGrade[courseName=French, term=2021-04, grade=3.1], CourseGrade[courseName=Composition, term=2021-01, grade=3.2], CourseGrade[courseName=Composition, term=2021-04, grade=3.4], CourseGrade[courseName=French, term=2021-01, grade=3.0]]]]
averageForFrenchIn2021_01 = Optional[2.9666665]
That looks correct, the average of ( 3.2 , 2.7 , 3.0 ) is 2.96….
studentsclass should be named using standard Java naming conventions, and since it represents a single student, should be the singularStudent.