I have an ArrayList composed of Student objects. These objects contain first name, last name, lab grade, project grade, exam grade, and total grade. I am trying to write a function that sorts the Student objects in the ArrayList based on their total grade.
Here's my Student class:
public class Student {
// fields
private String firstname;
private String lastname;
private int labgrade;
private int projectgrade;
private int examgrade;
private int totalgrade;
// constructor
public Student(String firstname, String lastname, int labgrade,
int projectgrade, int examgrade) {
this.firstname = firstname;
this.lastname = lastname;
this.labgrade = labgrade;
this.examgrade = examgrade;
this.totalgrade = labgrade + projectgrade + examgrade;
}
// method
public String toString() {
String s = firstname + " " + lastname + " has a total grade of "
+ totalgrade;
return s;
}
public int compareTo(Student s) {
return (totalgrade = s.totalgrade);
}
And here's what I tried to do to sort:
private ArrayList<Student> arraylist = new ArrayList<Student>();
public void SortStudent() {
Collections.sort(arraylist);
}
But that doesn't work because it says it can only work on List not ArrayList. Any help to fix my SortStudent method?
ArrayList is a List, the problem is that Student does not implement Comparable, and you didn't define the compareTo method, which you need to do to use the sort method from Collections.
You could do something similar to this:
public class Student implements Comparable<Student> {
//... the rest of the class
public int compareTo(Student s) {
return Integer.compare(this.grade, s.grade);
}
}
Another option would be to use lambda expressions with the method Collections.sort(List<T>, Comparator<? super T> c), where you don't need to implement Comparable:
public void sortStudent() {
Collections.sort(arraylist, (s1, s2) -> Integer.compare(s1.grade, s2.grade));
}
Collections.sort only works for types that implement Comparable:
public static <T extends Comparable<? super T>> void sort(List<T> list) {...}
Implementing Comparable<...> with Student is a bad choice in this case, since the sorting criteria are likely to change. e.g. sometimes you want to sort by first name, and sometimes by last name.
List<...> has a sort method that takes a Comparator, you could use that:
private ArrayList<Student> arraylist = new ArrayList<Student>();
...
public void SortStudent() {
arraylist.sort((x, y) -> Integer.compare(x.totalgrade, y.totalgrade));
}
class Student implements Comparable{
int rollno;
String name;
int grade;
Student(int rollno,String name,int grade){
this.rollno=rollno;
this.name=name;
this.grade=grade;
}
public int compareTo(Object obj){
Student st=(Student)obj;
if(grade==st.grade)
return 0;
else if(grade>st.grade)
return 1;
else
return -1;
}
Related
I am intrigued by the fact I noticed today
that for comparision in java
Integer provides compare method
Integer.compare(student1.age, student2.age);
String provides compareTo Method
Student1.firstName.compareTo(student2.firstName);
Just want to understand why so :/
Please refer example class here:
String firstName;
String lastName;
int age;
long studentId;
Student(){}
Student(String firstName, String lastName, int age, long studentId){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.studentId = studentId;
}
}
Camparator Implementations -
public class StudentFirstNameComparator implements Comparator<Student> {
#Override
public int compare(Student student1, Student student2) {
return student1.firstName.compareTo(student2.firstName);
}
}
public class StudentAgeComparator implements Comparator<Student> {
#Override
public int compare(Student student1, Student student2) {
return Integer.compare(student1.age, student2.age);
// either of the lines can be used.
// if(student1.age == student2.age)
// return 0;
// else if (student1.age>student2.age) {
// return 1;
// }else {
// return -1;
// }
}
}
The Integer class also provides a compareTo method, because it's Comparable like String is.
Take a look at Integer class's compare method, and notice that it has 2 int arguments and it's static. This way, one can compare two primitive ints safely without boxing them into Integers, which is what would occur with compareTo.
public class pro1{
static ArrayList <String> student = new ArrayList<String>();
static ArrayList <Integer> id = new ArrayList<Integer>();
String name;
int ID;
public pro1() {
this.name = "";
this.ID = 0;
}
public pro1(String name, int ID) {
this.name = name;
this.ID = ID;
}
public boolean addStudent(String name, int ID) {
student.add(name);
id.add(ID);
return true;
}
/*#Override
public String toString() {
return name + ID;
}*/
public static void main(String args[]) {
pro1 stu = new pro1();
stu.addStudent("john", 1);
stu.addStudent("johnny", 2);
System.out.println(stu);
}
}
I want to print out both the name of the student and the student id using ArrayList. however, I'm not sure how to do that since in this class I can only print out the ArrayList of names or the ArrayList of id. I'm thinking of maybe using another class to create a student object, but I'm not sure how to do so.
great question, I think the best solution for this would be to create a Student object just like you thought!
public static class Student {
private final String name;
private final int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
}
#Override
public String toString() {
return String.format("name=%s, id=%s", name, id);
}
}
public static class School {
private final List<Student> students;
public School(List<Student> students) {
this.students = students;
}
public void add(Student student) {
students.add(student);
}
public List<Student> getStudents() {
return students;
}
}
public static void main(String... args) {
School school = new School(new ArrayList<>());
school.add(new Student("jason", 1));
school.add(new Student("jonny", 2));
school.getStudents().forEach(System.out::println);
}
Non-OOP
Loop the pair of lists.
First sanity-check: Are the two lists the same size?
if( students.size() != ids.size() ) { … Houston, we have a problem }
Then loop. Use one index number to pull from both lists.
for( int index = 0 ;
index < students.size() ;
index ++
)
{
System.out.println(
students.get( index ) +
" | " +
ids.get( index )
) ;
}
OOP
The object-oriented approach would be to define a class. The class would have two member fields, the name and the id of the particular student.
Then create a method that outputs a String with your desired output.
All this has been covered many times on Stack Overflow. So search to learn more. For example: Creating simple Student class and How to override toString() properly in Java?
Uncomment and modify your toString() method as below. It will print both student and id.
#Override
public String toString() {
return student.toString() + id.toString();
}
If you want to have Student to Id mapping, best is to have them in Map collection. Id as key and student name as value.
I have a program I am working with to help me practice my coding skills. The program has the following scenario: there is a classroom of 20 students, where the record is taken of the students' names, surnames, and age. Half of these students take part in the school's athletics. Here, record is kept of their races that they have done and the ones they've won.
In this program, I have three classes:
runStudents - class with main method
Students (String name, String surname, int age) - parental class
AthleticStudents (String name, String surname, int age, int races, int victories) - sub class
The user should be able to add another race (and win) to the object. As seen by the code provided, an Array is created to store the 20 Students objects. I have to be able to access a method to alter the object in the array, but this method is not in the parental class (the class the objects are created from.
public class Students
{
private String name;
private String surname;
private int age;
public Students()
{
}
public Students(String name, String surname, int age)
{
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName()
{
return this.name;
}
public String getSurname()
{
return this.surname;
}
public double getAge()
{
return this.age;
}
public void setName(String name)
{
this.name = name;
}
public void setSurname(String surname)
{
this.surname = surname;
}
public void setAge(int age)
{
this.age = age;
}
public String toString()
{
return String.format("name\t\t: %s\nsurname\t\t: %s\nage\t\t: %s",
this.name, this.surname, this.age);
}
}
public class AthleticStudents extends Students
{
private int races;
private int victories;
public AthleticStudents()
{
}
public AthleticStudents(String name, String surname, int age, int
races, int victories)
{
super(name, surname, age);
this.races = races;
this.victories = victories;
}
public int getRaces()
{
return this.races;
}
public int getVictories()
{
return this.victories;
}
public void setRaces(int races)
{
this.races = races;
}
public void setVictories(int victories)
{
this.victories = victories;
}
public void anotherRace()
{
this.races = this.races + 1;
}
public void anotherWin()
{
this.victories = this.victories + 1;
}
public String toString()
{
return super.toString() + String.format("\nnumber of races\t:
%s\nnumber of wins\t: %s", this.races, this.victories);
}
}
public class runStudents
{
public static void main(String[]args)
{
Students[] myStudents = new Students[20];
myStudents[0] = new Students("John", "Richards", 15);
myStudents[1] = new AthleticStudents("Eva", "Grey", 14, 3, 1);
myStudents[2] = new Students("Lena", "Brie", 15);
for (int i = 0; i < 3; i++)
System.out.println(myStudents[i].toString() + "\n\n");
}
}
I want to be able to do the following:
AthleticStudents[1].anotherRace();
but cannot do so as the array object is derived from the parental class, and I declared the method in the sub class. How can I link the two?
I assume that you create an array of the parent class instances. Just cast the instance this way (you better check whether the element is the instance of a subclass):
if (AthleticStudents[1] instanceof AthleticStudents)
((AthleticStudents) AthleticStudents[1]).anotherRace();
I'm not sure if this is exactly what you're looking for but it worked well for me. Instead of trying to access AthleticStudents method anotherRace() like that, try this in your main method.
Students[] myStudents = new Students[20];
myStudents[0] = new Students("John", "Richards", 15);
myStudents[1] = new AthleticStudents("Eva", "Grey", 14, 3, 1);
myStudents[2] = new Students("Lena", "Brie", 15);
AthleticStudents addRace= (AthleticStudents)myStudents[1];
addRace.anotherRace(); //This will increment Eva's race count to 4
for (int i = 0; i < 3; i++)
System.out.println(myStudents[i].toString() + "\n\n");
All I did was cast the element into an object AthleticStudents named 'addRace'. By casting myStudents[1] to this new object you are able to access all of AthleticStudents methods.
I just saw the other answer posted which works just as well!
Hope this helps!
I’m not sure that i understand your question, because you are a bit inconsistent with your capitalization. runStudents is a class, while AthleticStudents is both a class and an array. But i’ll try.
IF i did understand your question, you have an array Student[] studentArray. Some Student objects in studentArray are AthleticStudents, others are not. You have a specific AthleticStudent eva which is in studentArray[] having let’s say index 1, and you want to add to her anotherRace(). Your call studentArray[1].anotherRace does not compile because the compiler treats that element as a Student and not as a AthleticStudent.
The trick is to cast the element to AthleticStudent. I omit the test of the element of being really an AthleticStudent; you will have to do that test in your code.
((AthleticStudent) studentArray[1]).anotherRace();
I have been reading on how to program Java 8 Polymorphism.
I have this code:
public class Person
{
// instance variables - replace the example below with your own
private String lastname;
private String firstname;
private int age;
private boolean married;
private float salary;
/**
* Constructor for objects of class Person
*/
public Person(String lastname, String firstname, int age, boolean married, float salary)
{
// initialise instance variables
this.lastname = new String(lastname);
this.firstname = new String(firstname);
this.age = age;
this.married = married;
this.salary = salary;
}
public String getLastName() {return lastname;}
public String getFirstName() {return firstname;}
public int getAge() {return age;}
public boolean isMarried() {return married;}
public float getSalary() {return salary;}
}
public class MarriedPerson extends Person
{
// instance variables - replace the example below with your own
private int children;
/**
* Constructor for objects of class MarriedPerson
*/
public MarriedPerson(String lastname, String firstname, int age, float salary, int children)
{
// initialise instance variables
super(lastname, firstname, age, true, salary);
this.children = children;
}
public int getNoOfChildren()
{
// put your code here
return children;
}
}
abstract class MyTester
{
public static void main(String[] args) {
Person p1 = new Person("Kings", "Paul", 22, true, 1200f);
MarriedPerson mp1 = new MarriedPerson("Tront", "Betty", 31, 980.5f, 3);
System.out.print(p1.getFirstName()+" "+p1.getLastName()+" is "
+p1.getAge()+" years old, gets a "+p1.getSalary()
+" Euros salary and is");
if (p1.isMarried() == false)
System.out.print(" not");
System.out.println(" married.");
System.out.print(mp1.getFirstName()+" "+mp1.getLastName()
+" is " +mp1.getAge()+ " years old, gets a " + mp1.getSalary()
+" Euros salary and is" + " married with ");
if (mp1.getNoOfChildren() > 0)
System.out.print(mp1.getNoOfChildren());
else System.out.print("no");
System.out.println(" children.");
}
}
Reading from a book, I have not seen an abstract class that contains the main function so I am a bit confused.
Why have we declared MyTester class as abstract? Is this necessary?
I have now created a printInfo method in class Person. See following code:
public class Person
{
// instance variables - replace the example below with your own
private String lastname;
private String firstname;
private int age;
private boolean married;
private float salary;
/**
* Constructor for objects of class Person
*/
public Person(String lastname, String firstname, int age, boolean married, float salary)
{
// initialise instance variables
this.lastname = new String(lastname);
this.firstname = new String(firstname);
this.age = age;
this.married = married;
this.salary = salary;
}
public String getLastName() {return lastname;}
public String getFirstName() {return firstname;}
public int getAge() {return age;}
public boolean isMarried() {return married;}
public float getSalary() {return salary;}
public void printInfo(){
System.out.print(p1.getFirstName()+" "+p1.getLastName()+" is "
+p1.getAge()+" years old, gets a "+p1.getSalary()
+" Euros salary and is");
if (p1.isMarried() == false)
System.out.print(" not");
System.out.println(" married.");
}
}
abstract class MyTester
{
public static void main(String[] args) {
Person p1 = new Person("Kings", "Paul", 22, true, 1200f);
MarriedPerson mp1 = new MarriedPerson("Tront", "Betty", 31, 980.5f, 3);
p1.printInfo();
mp1.printInfo();
}
}
When I compile the modified code it give me the error: cannot find symbol - variable p1. Why is that? What do I need to do in order to fix that?
What advantages second code has over first one?
It does not make sense MyTester to be abstract since it does not have any abstract method. The only reason might be to prevent the instantiation of MyTester class because it might not make sense for an instance to exist.
MyTester is declared abstract so you can't create any instances of it (there is no reason you would want to). See this link, it says:
An abstract class is a class that is declared abstract—it may or may
not include abstract methods. Abstract classes cannot be instantiated,
but they can be subclassed.
When I compile the modified code it give me the error: cannot find symbol - variable p1. Why is that? What do I need to do in order to fix that?
For future reference: You should create a new question and not edit your existing one. Also, if someone solved your first problem you should allways be so nice as to accept their answer. ;)
Anyway: You are getting that error because your object is only "known" as p1 in your main class.
In your "printInfo()" method you are trying to have the objects do calls on itself. So either just remove the "p1." part and just call the methods like "getFirstName()", or explicitly call "this.getFirstName()".
("this" is a java keyword refering to the current object instance.)
A tipp for you: Get a good JAVA IDE like Eclipse (https://eclipse.org/) and you will see simple errors like those even before compiling.
No. It makes no difference, as the class is never extended or used except as an entrypoint.
I finished all the classes except for the student class. I don't understand how to approach it. Here is the prompt.
Extend the Person class developed in
lab1 to derive classes for students,
hourly employees, and full-time
salaried employees. Determine an
appropriate class inheritance
hierarchy. These classes should have
the following fields, necessary
constructors, and appropriate access
and modifier methods.
for all employees:
*department
full-time employees:
*salary
hourly employees:
*hourly rate
*number of hours worked each week(4weeks)
the hourly employee class should
contain the necessary methods that
will print the total hours (four- week
total), average hours per week worked
by each employee, and the total wages
during a four-week period.
student:
*classes taken and grades for each class (use an ArrayList)
The student class should contain the
necessary methods to print the
transcript for each student
(write a tester class to test your
classes)
How should I use an arraylist for the student class?
I'm only going to post the relevant classes
public class Person { private String first; private String last; private static int idNumber = 1001; int Id ; private String full;
Person(){
}
Person(String fn,String ln){
first = fn;
last = ln;
Id = idNumber++;
full = first +" "+ last;
}
static int getidNumber(){
return idNumber;
}
void setfirst(String fn) {
first = fn;
}
String getfirst(){
return first; }
void setlast(String ln){
last = ln; }
String getlast(){
return last; }
#Override
public String toString(){
String blah = "First name: " +first+ " Last Name:" +last+ "\tThe full name is: "+full+" Id#"+Id;
return blah;
}
}
import java.util.*;
public class Student extends Person{
Student (String fn, String ln){
super(fn,ln);
}
}
Thank you in advance for all advices and suggestions.
I would use a map here, but since an ArrayList is required, I would do something like that:
public class Student extends Person {
private List<ClassGrade> classes = new ArrayList<ClassGrade>();
public List<ClassGrade> getClassGrades() {
return new ArrayList<ClassGrade>(classes);
}
public void addClass(String clazz, int grade) {
classes.add(new ClassGrade(clazz, grade));
}
public static class ClassGrade {
String clazz;
int grade;
public ClassGrade(String clazz, int grade) {
this.clazz = clazz;
this.grade = grade;
}
public String getClazz() {
return clazz;
}
public int getGrade() {
return grade;
}
}
}
import static java.lang.System.*;
class Student extends Person
{
protected int avMark;
String classTaken
public Student()
{
}
public Student(String nameInput, int ageInput, String class)
{
super(nameInput, ageInput);
classTaken = class;
}
public void setClasTaken(String className){
classTaken = classname;
}
public String setClasTaken(){
return classTaken;
}
public void register()
{
super.register();
out.println("Classes taken " +classTaken
out.println("Average mark is " + avMark);
}
}
here is something to start you off
this class inherits everything from the person class.