I want to sort students by their roll numbers. I know how to sort an arraylist of integers using merge sort, but sorting an ArrayList of type Student is different.
my Student class contains the following properties:
public static class Student
{
String name;
int rollNum, WebMark, dsMark, dmMark;
public Student(String name, int rollNum, int WebMark, int dsMark, int dmMark)
{
this.name = name;
this.rollNum = rollNum;
this.WebMark = WebMark;
this.dsMark = dsMark;
this.dmMark = dmMark;
}
}
I've seen people use Comparators to sort ArrayLists of object's properties. However, they use it for built-in sorting like the following line (which is straightforward):
Collections.sort(Database.arrayList, new CustomComparator());
However, I want to use my mergesort functions that I wrote in my Student class. But I still don't understand how am I going to pass the property 'rollNum' into the mergesort function and how are other properties in the ArrayList are going to be moved accordingly? I've never seen this anywhere in Google.
Here is my full code:
package student;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Comparator;
public class Main
{
public static class Student
{
String name;
int rollNum, WebMark, dsMark, dmMark;
public Student(String name, int rollNum, int WebMark, int dsMark, int dmMark)
{
this.name = name;
this.rollNum = rollNum;
this.WebMark = WebMark;
this.dsMark = dsMark;
this.dmMark = dmMark;
}
public String getName()
{
return name;
}
public int getRollNum()
{
return rollNum;
}
public int getWebMark()
{
return WebMark;
}
public int getDSMark()
{
return dsMark;
}
public int getDMMark()
{
return dmMark;
}
public static void addStudent(ArrayList<Student> studentArray)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter Name: ");
String name = input.next();
System.out.println("Enter Roll Number");
int rollNum = input.nextInt();
System.out.println("Enter Web Mark:");
int webMark = input.nextInt();
System.out.println("Enter Data Structure Mark:");
int DSMark = input.nextInt();
System.out.println("Enter Discrete Math Mark:");
int DMMark = input.nextInt();
//create this student profile in array
Student newStudent = new Student(name,rollNum,webMark,DSMark,DMMark);
studentArray.add(newStudent);
}
public static void findStudent(int rollNum, ArrayList<Student> studentArr)
{
for(int i = 0; i < studentArr.size(); i++)
{
if(studentArr.get(i).getRollNum()==rollNum)
{
System.out.println("Roll Number: " + studentArr.get(i).getRollNum() +
", Name: " + studentArr.get(i).getName() +
", Web Grade: " + studentArr.get(i).getWebMark() +
", Data Structure Grade: " + studentArr.get(i).getDSMark() +
", Discrete Math Grade: " + studentArr.get(i).getDMMark());
}
else
{
System.out.println("Couldn't find student.");
}
}
}
public static void deleteStudent(ArrayList<Student> studentArr)
{
System.out.println("Enter Student Roll Number: ");
Scanner input = new Scanner(System.in);
int rollNum = input.nextInt();
for(int counter = 0; counter < studentArr.size(); counter++)
{
if(studentArr.get(counter).getRollNum() == rollNum)
{
studentArr.remove(counter);
}
}
}
public String toString()
{
return name + " " + rollNum + " " + WebMark + " " + dsMark + " " + dmMark;
}
public static double avg(ArrayList<Student> studentArr)
{
double[] avgArr = new double[studentArr.size()];
double max = 0.0;
for(int counter = 0; counter < studentArr.size(); counter++)
{
avgArr[counter] = (studentArr.get(counter).getWebMark() +
studentArr.get(counter).getDSMark() + studentArr.get(counter).getDMMark())/(3);
if(avgArr[counter] > max)
{
max = avgArr[counter];
}
}
return max;
}
public int compareTo(Student studCompare)
{
int compareRollNum = ((Student) studCompare).getRollNum();
//ascending order
return this.rollNum - compareRollNum;
}
/*Comparator for sorting the array by student name*/
public static Comparator<Student> StuNameComparator = new Comparator<Student>()
{
public int compare(Student s1, Student s2)
{
String StudentName1 = s1.getName().toUpperCase();
String StudentName2 = s2.getName().toUpperCase();
//ascending order
return StudentName1.compareTo(StudentName2);
//descending order
//return StudentName2.compareTo(StudentName1);
}
};
/*Comparator for sorting the array by student name*/
public static Comparator<Student> StuRollno = new Comparator<Student>()
{
public int compare(Student s1, Student s2)
{
int rollno1 = s1.getRollNum();
int rollno2 = s2.getRollNum();
//ascending order
return rollno1-rollno2;
//descending order
//return StudentName2.compareTo(StudentName1);
}
};
public static <T extends Comparable<T>> List<T> mergeSort(List<T> m)
{
// exception
if (m==null) throw new NoSuchElementException("List is null");
// base case
if (m.size() <= 1) return m;
// make lists
List<T> left = new ArrayList<>();
List<T> right = new ArrayList<>();
// get middle
int middle = m.size()/2;
// fill left list
for (int i = 0; i < middle; i++)
{
if (m.get(i)!=null) left.add(m.get(i));
}
// fill right list
for (int i = middle; i < m.size(); i++)
{
if (m.get(i)!=null) right.add(m.get(i));
}
// recurse
left = mergeSort(left);
right = mergeSort(right);
// merge
return merge(left,right);
}
private static <T extends Comparable<T>> List<T> merge(List<T> left, List<T> right)
{
List<T> result = new ArrayList<>();
// merge
while (!left.isEmpty() && !right.isEmpty())
{
if (left.get(0).compareTo(right.get(0)) <= 0)
{
result.add(left.remove(0));
}
else
{
result.add(right.remove(0));
}
}
// cleanup leftovers
while (!left.isEmpty())
{
result.add(left.remove(0));
}
while (!right.isEmpty())
{
result.add(right.remove(0));
}
return result;
}
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int userChoice = 0;
int userChoice2 = 0;
ArrayList<Student> studentArr = new ArrayList<Student>(); //array size is 6
System.out.println("1- Merge Sort");
System.out.println("2- Shell Sort");
System.out.println("3- Quit");
userChoice2 = input.nextInt();
if (userChoice2 == 1 || userChoice2 == 2)
{
do {
System.out.println("1- Add a New Record");
System.out.println("2- Sort by Student Name");
System.out.println("3- Sort by Roll Number");
System.out.println("4- Delete a Student Specific Record");
System.out.println("5- Display a Student Specific Record");
System.out.println("6- Search");
System.out.println("7- Display the Highest Average");
System.out.println("8- Print"); //print the array size, sort time, and number of comparisons to the screen.
System.out.println("9- Quit");
System.out.println("Select your Option: \n");
userChoice = input.nextInt();
switch (userChoice) {
case 1:
Student.addStudent(studentArr);
break;
case 2:
if (userChoice2 == 1) {
//call mergesort function
} else if (userChoice2 == 2) {
//call shell sort function
}
case 3:
if (userChoice2 == 1) {
//call mergesort function
} else if (userChoice2 == 2) {
//call shell sort function
}
case 4:
Student.deleteStudent(studentArr);
break;
case 5:
System.out.println("Enter Student Roll Number: ");
int rollNum_ = input.nextInt();
Student.findStudent(rollNum_, studentArr);
break;
case 6:
case 7:
double highestAvg = Student.avg(studentArr);
System.out.println("Highest Average is: " + highestAvg);
break;
case 8:
System.out.println("Printing students...");
System.out.print(studentArr);
System.out.println("\n");
break;
case 9:
}
} while (userChoice != 9);
}
else
{
return;
}
input.close();
}
}
Your Student is already Comparable and it already compares to other Student instances using rollNum field, so the current implementation using compareTo() should already sort on that field.
But if you want to sort using a different ordering, you could write a Comparator and change your sorting method like so:
private static <T> List<T> merge(List<T> left, List<T> right, Comparator<? super T> comparator) {
.. use comparator.compare(a, b) instead of a.compareTo(b)
}
Here, you don't need to restrict T with Comparable.
in order to sort anything , the object must be comparable by somewhat. In java, there are 2 ways to do it for objects (like student):
Comparable and Comparator.
That being said, your object must implement Comparable interface and then write implementation of the necessary method compareTo where you list how you want then to compare to each other.
Another way is to implement Comparator interface and write implementation for compare method.
Once that is done, you can sort the collection with Collection.sort ..... method.
Related
This is the code that is meant to call a class called Couple and yet
it doesn't recognize the class why is this?
public class AgencyInterFace {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
Couple c = new Couple();
int choice, position;
showSelection();
choice = console.nextInt();
while (choice != 9) {
switch (choice) {
case 1:
addCouple();
break;
case 2:
position = console.nextInt();
testCouple(position);
break;
case 3:
position = console.nextInt();
displayCouple(position);
break;
case 9:
break;
default:
System.out.println("Invalid Selection");
} //end switch
showSelection();
choice = console.nextInt();
}
}
public static void showSelection() {
System.out.println("Select and enter");
System.out.println("1 - add a new couple");
System.out.println("2 - test a couple");
System.out.println("3 - display couple");
System.out.println("9 - exit");
}
public static void addCouple() {
Scanner console = new Scanner(System.in);
String herName, hisName;
int herAge, hisAge, ageDiff;
System.out.print("her name: ");
herName = console.nextLine();
System.out.print("her age: ");
herAge = console.nextInt();
System.out.print("his name: ");
hisName = console.nextLine();
System.out.print("his age: ");
hisAge = console.nextInt();
ageDiff = herAge - hisAge;
c.addData(herName, herAge, ageDiff, hisName, hisAge, ageDiff);
}
public static void testCouple(int position) {
System.out.println(c.test(position));
}
public static void displayCouple(int position) {
System.out.println(c.display(position));
}
public static void averageAge(int position) {
System.out.println(c.avgAge());
}
public static void maxDifference(int position) {
System.out.println(c.maxDif(position));
}
public static void averageDifference(int position) {
System.out.println(c.avgDif(position));
}
}//end of class
This code is the class that is meant to be called and that is not
being recognized and is unable to be called.
public class Couple {
final private int MAX = 5;
private Person[] p1, p2;
private int total;
public Couple() {
p1 = new Person[MAX];
p2 = new Person[MAX];
total = 0;
}
private void setData1(Person p, String name, int age, int ageDiff) {
p.setName(name);
p.setAge(age);
}
public String test(int pos) {
if (pos != -1) {
if (p1[pos].getAge() < p2[pos].getAge()) return ("GOOD FOR
"+p2[pos].getName()+" !");
else return ("GOOD
FOR "+p1[pos].getName()+" !");
}
return "error";
}
public void addData(String name1, int age1, int ageDiff1, String
name2, int age2, int ageDiff2) {
p1[total] = new Person();
p2[total] = new Person();
setData1(p1[total], name1, age1, ageDiff1);
setData1(p2[total], name2, age2, ageDiff2);
total++;
}
public String display(int position) {
if (position != -1)
return ("p1: " + p1[position].getName() + "
"+p1[position].getAge()+" / n "+" p2:
"+p2[position].getName()+"
"+p2[position].getAge());
else
return ("error");
}
public String avgAge(int position) {
double avg = 0;
double sum = 0.0;
for (int i = 0; i < position; i++) {
sum += p1[total].getAge();
sum += p2[total].getAge();
}
avg = sum / position;
return ("The average age is: " + avg);
}
public void ageDifference(int position) {
double ageDif = 0.0;
double ageSum = 0.0;
for (int i = 0; i < position; i++) {
if (p1[total].getAge() < p2[total].getAge()) {
ageSum = p2[total].getAge() - p1[total].getAge();
} else {
ageSum = p1[total].getAge() - p2[total].getAge();
}
ageSum = ageDif;
}
}
}
Is this have something to do with the name of the 'Couple' file or how
I call the class. I am getting an 'Undeclared Variable' error.
You defined c inside your main() method. Therefore it is not visible in your other methods. Either pass c as a parameter to your other methods or make it a (static) property of the AgencyInterFace class instead of a local variable of main().
USING STATIC METHODS
If you want to call a method of the class, e.g. test(int position), without creating a variable c, you need to make this method static:
public static String test(int pos) {
if (pos!=-1) {
if (p1[pos].getAge()<p2[pos].getAge()) return("GOOD FOR "+p2[pos].getName()+"!");
else return("GOOD FOR"+p1[pos].getName()+"!");
}
return "error";
}
In this case, your arrays p1[] and p2[] would also need to be static --> they would only be created one time.
And example for making your arrays static:
private static Person[] p1 = new Person[MAX],
p2 = new Person[MAX];
Now you can call this method of the class using Couple.test(position) and it will return a String.
USING NON-STATIC METHODS
If you want to create multiple references of the class Couple, in that p1[] and p2[] should contain different values, you need to create a reference of the class Couple.
You can implement this by telling the program, what c is:
Couple c = new Couple();
Edit:
I see that you have created a couple, but not at the right place. If you create your couple inside of the main() method, you cannot use it anywhere except in this method. You should declare it in your class:
public class AgencyInterFace {
private static Couple c = new Couple(); //<-- here
// main-method
// other methods
}
I'm working on a program where I'm inputting values(String and int) into arrays, putting those values into an objects which go into an array list to be sorted by the the int value. When I run the program though, it prints out:
Sorted List Entries:
Item Name:null---Quant:0
Item Name:null---Quant:0
Item Name:null---Quant:0 //etc..
I'm trying to learn on my own here but I'm not sure what to do.
My main class:
import java.io.*;
import java.util.*;
public class InputItem
{
public static void main(String args[])
{
String again;
String names[] = new String[100];
int quant[] = new int[100];
int row=0;
do{
System.out.println("Please input assignment name:");
Scanner newName = new Scanner(System.in);
String name = newNamet.next();
names[row] =name;
System.out.println("Please input assignment quant:");
Scanner quantI = new Scanner(System.in);
int quantity = quantI.nextInt();
quant[row] = quantity;
System.out.println("Would you like to add another item? Enter 'Yes' or 'No'");
Scanner input = new Scanner(System.in);
again = input.next();
row++;
}
while(again.equalsIgnoreCase("Yes"));
List<Items> work = new ArrayList<Items>();
for(int count = 0; count<row; count++)
{
work.add(new Items((names[row]),(quant[row])));
}
Collections.sort(work, new MyComp());
System.out.println("Sorted List Entries: ");
for(Items e:work)
{
System.out.println(e);
}
}
}
Class with Comparator:
import java.util.*;
class MyComp implements Comparator<Items>
{
#Override
public int compare(Items e1, Items e2)
{
if((e1).getQuant()< (e2).getQuant())
{
return 1;
}
else
{
return -1;
}
}
}
public class Items
{
private String name;
private int quant;
public Items(String n, int q)
{
this.name = n;
this.quant = q;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getQuant()
{
return quant;
}
public void setQuant(int quant)
{
this.quant = quant;
}
public String toString()
{
return "Item Name:" + this.name+"---Quant:" +this.quant;
}
}
The problem is here...
for (int count = 0; count < row; count++) {
work.add(new Items((names[row]), (quant[row])));
}
You're using row, which was defined in the previous section of code to keep track of which element you were updating, but is now pointing to the next element in the array (or an empty element). This basically means you are constantly adding the same (empty) values to your Items
Instead, you should be using count
for (int count = 0; count < row; count++) {
work.add(new Items((names[count]), (quant[count])));
}
I'm making a number guessing game for a school project in Java, which I'm extremely bad at. I've got everything to work with classes and the guessing part, but now I'm going to create a top players list and sort it and I have no idea how.
This is the code I use for guessing and creating objects of the player.
public static void spela() {
int nummer= ((int) (1+Math.random()*100));
Scanner input = new Scanner(System.in);
Scanner s_input = new Scanner(System.in);
boolean ratt = false;
int forsok = 1;
int gissning;
String namn;
while(ratt==false) {
System.out.println("Gissa nummer: ");
gissning = input.nextInt();
if(gissning == nummer) {
System.out.println("Grattis du gissade rätt! Tog: " + forsok + " försök att gissa rätt!");
System.out.println("Skriv in namn: ");
namn = s_input.nextLine();
for(int i=0;i<cr;i++) {
if(namn.equals(allaspelare[i].namn)) {
allaspelare[i].setpoang(forsok);
ratt=true;
menu();
}
}
allaspelare[cr] = new spelare(namn);
allaspelare[cr].setpoang(forsok);
cr++;
ratt=true;
menu();
}
if(gissning > nummer) {
System.out.println("Du gissade: " + gissning + " och det var för mycket!");
}
if(gissning < nummer) {
System.out.println("Du gissade: " + gissning + " och det var för lite!");
}
forsok++;
}
}
this is the "spelare" class:
public class spelare {
int[] poang = new int[100];
int antal;
String namn;
public spelare(String innamn) {
namn = innamn;
}
public void setpoang(int inpoang) {
poang[antal] = inpoang;
antal++;
}
}
as you see one player can have multiple scores so that's the problem I can't get it right in my mind how I'm going to sort it so the output if I wan't to get out the score chart will come like:
testplayer1: 9
testplayer2: 11
testplayer3: 34
So basically I need help to code a method that goes through the class and sort it and output it as above! Any help/sources is extremely appreciated!
And commented code would be extremely appreciated so I can learn!
EDIT:
I've been searching for hours, and the only thing that I found was this:
public static void sortera(int[] lista, int plats) {
int i;
if (lista.length < 2) return;
int temp;
for(int n=1; n<lista.length; n++) {
temp=lista[n];
i = n - 1;
while(i >=0 && lista[i] > temp) {
lista[i+1] = lista[i];
}
lista[i+1] = temp;
}
allaspelare[plats].poang = lista;
}
And this is how I called it:
case 5:
sortera(allaspelare[0].poang, 0);
break;
but this doesn't do anything..
The structure you use is simply bad. Instead you should use pairs of names and scores. This way multiple scorepairs with the same name exist, but you can easily sort them.
public class Score implements Comparable<Score>{
private int score;
private String name;
public Score(String name , int score){
this.score = score;
this.name = name;
}
//getters and setters as required
public int compareTo(Score s){
return score - s.score;
}
}
This aswell allows you to directly compare Scoreobjects to eachother. This way a list of Score objects can easily be sorted via Collections.sort(someList).
I am attempting to sort the values in my program using the Bubble Sort method. I believe that my code in the organisedRoom method is correct. However when I run the code, add some customers and then attempt to sort them, the program crashes. If anyone can please point me in the right direction I would greatly appreciate it.
package test;
import java.io.IOException;
import java.util.Scanner;
public class Test {
private class Customer implements Comparable<Customer>{
private String name;
public Customer(String name) {
this.name = name;
}
//Override to stop the program returning memory address as string
#Override
public String toString() {
return name;
}
#Override
public int compareTo(Customer c) {
return name.compareTo(c.name);
}
}
//Array to store customers
public Customer[] customers;
public Scanner input = new Scanner(System.in);
public Test(int nRooms) throws IOException {
customers = new Test.Customer[nRooms];
System.out.println("Welcome to the Summer Tropic Hotel\n");
chooseOption();
}
final JFileChooser fc = new JFileChooser();
// Call new Hotel with int value to allocate array spaces
public static void main(String[] args) throws IOException {
Test t = new Test(11);
}
// New procedure to return User input and point to next correct method
private String chooseOption() throws IOException {
// Set to null, this will take user input
String choice;
//Menu options
System.out.println("This is the Hotel Menu. Please choose from the following options:\n");
System.out.println("A: " + "This will add a new entry\n");
System.out.println("O: " + "View booked rooms, in order of customers name.\n");
System.out.println("X: " + "Exit the program\n");
// Take user input and assign it to choice
choice = input.next();
// Switch case used to return appropriate method
switch (choice.toUpperCase()) {
case "A" :
System.out.println("");
addCustomer();
return this.chooseOption();
case "O" :
System.out.println("");
organisedRoom();
return this.chooseOption();
case "X":
System.exit(0);
}
return choice;
}
// Add a new customer to the Array
public void addCustomer() throws IOException {
// New variable roomNum
int roomNum = 1;
// Loop
do {
// Take user input as room number matching to array index - 1
System.out.println("Please choose a room from 1 to 10");
roomNum = input.nextInt() - 1;
// If room is already booked print this
if (customers[roomNum] != null) {
System.out.println("Room " + roomNum + 1 + " is not free, choose a different one.\n");
this.addCustomer();
}
// Do until array index does not equal to null
} while (customers[roomNum]!= null);
System.out.println("");
// User input added to array as name replacing null (non case-sensetive)
System.out.println("Now enter a name");
customers[roomNum] = new Customer(input.next().toLowerCase());
// Customer (name) added to room (number)
System.out.println(String.format("Customer %s added to room %d\n", customers[roomNum], roomNum + 1));
}
private void organisedRoom() {
boolean flag = true;
Customer temp;
int j;
while (flag) {
flag = false;
for (j = 0; j < customers.length - 1; j++) {
if (customers[j].compareTo(customers[j+1]) < 0) {
temp = customers[j];
customers[j] = customers[j + 1];
customers[j + 1] = temp;
flag = true;
}
}
}
}
}
I think this is because the initialisation of the array adds null to all the array index places.
The stack trace is as follows:
Exception in thread "main" java.lang.NullPointerException
at test.Test$Customer.compareTo(Test.java:34)
at test.Test.organisedRoom(Test.java:133)
at test.Test.chooseOption(Test.java:83)
at test.Test.chooseOption(Test.java:79)
at test.Test.chooseOption(Test.java:79)
at test.Test.<init>(Test.java:46)
at test.Test.main(Test.java:55)
Java Result: 1
It fails because you create Customer[] which will be initialized with11 null references. If you want to order them all elements in the array will be compared. Which lead into the java.lang.NullPointerException.
Store the Customer in an ArrayList. Then you should be able to prevent this error.
edit
If you really need to stick as close as possible to your current code. The following would fix your sorting. (don't use this solution for a real life project)
private void organisedRoom() {
for (int i = customers.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (customers[j + 1] == null) {
continue;
}
if (customers[j] == null ||customers[j + 1].compareTo(customers[j]) < 0) {
Customer temp = customers[j + 1];
customers[j + 1] = customers[j];
customers[j] = temp;
}
}
}
System.out.println("show rooms: " + Arrays.toString(customers));
}
edit 2
To keep most of your current code, you might store the room in the Customer instance (which I personally would not prefer).
// change the constructor of Customer
public Customer(String name, int room) {
this.name = name;
this.room = room;
}
// change the toString() of Customer
public String toString() {
return String.format("customer: %s room: %d", name, room);
}
// store the Customer like
customers[roomNum] = new Customer(input.next().toLowerCase(), roomNum);
Your implementation of Bubble Sort is incorrect. It uses nested for loops.
for(int i = 0; i < customers.length; i++)
{
for(int j = 1; j < (customers.length - i); j++)
{
if (customers[j-1] > customers[j])
{
temp = customers[j-1];
customers[j-1] = customers[j];
customers[j] = temp;
}
}
}
I'm starting to learn object orientation in my course and we have an object class called students. An object of the studentsclass stores the instance variables: studentName, studentNumber, and studentGPA. I have a boolean method in my object class that determines whether the student is a failing student or not (the student is failing if their GPA is > 2.0) and then I have a method in my worker class that is supposed to accept the array of students objects, and then if the student is failing, it replaces that object with "null".
My problem is that I'm having a hard time replacing the students objects with null, since java keeps throwing me or some such. Here's what I've tried:
public static void removeFailingStudents(Student[] students)
{
int count;
for (count=0; count<students.length; count++)
{
if(students[count].isFailing())
{
students[count] = null;
}
}
}
and
public static void removeFailingStudents(Student[] students)
{
int count;
for (count=0; count<students.length; count++)
{
if(students[count].isFailing())
{
students[count] = "null";
}
}
}
but when I compile/run these attempts it either throws me an exception or it yells at me because it is not of the type Student. How do I set an item in an array of objects to null?? Thanks for the help!
Here's my full code:
public class L2Q1
{
public static void main(String[] parms)
{
process();
System.out.println("\nEnd of processing.");
}
public static void process()
{
Student[] students;
Student[] newStudents;
students = getStudents();
printStudents(students);
printAverageGPA(students);
printHonourStudents(students);
removeFailingStudents(students);
printStudents(students);
newStudents = compactStudents(students);
printStudents(students);
printStudents(newStudents);
}
public static void printStudents(Student[] students)
{
int count;
System.out.println("Students:");
for (count=0; count<students.length; count++)
{
System.out.println(students[count].toString());
}
System.out.println();
}
public static void printAverageGPA(Student[] students)
{
double sumGPA;
int count;
sumGPA = 0;
for (count=0; count<students.length; count++)
{
sumGPA += students[count].getGPA();
}
double average = sumGPA / count;
System.out.println("The average GPA is " + average);
System.out.println();
}
public static void printHonourStudents(Student[] students)
{
int count;
System.out.println("Honour students:");
for (count=0; count<students.length; count++)
{
if(students[count].isHonourStudent())
{
System.out.println(students[count].toString());
}
}
System.out.println();
}
public static void removeFailingStudents(Student[] students)
{
int count;
for (count=0; count<students.length; count++)
{
if(students[count].isFailing())
{
students[count] = null;
}
}
}
public static Student[] compactStudents(Student[] students)
{
Student[] newStudents;
int count1;
int count2;
System.out.println("Compacting failing students.");
System.out.println();
count1 = 0;
for (count2=0; count2<students.length; count2++)
{
}
newStudents = new Student[0];
return newStudents;
}
public static Student[] getStudents()
{
Student[] students = new Student[]
{
new Student(7654321, "Lara Zhivago", 3.75),
new Student(7654322, "Betty Brown", 1.9),
new Student(7654323, "Chris Cross", 0.5),
new Student(7654324, "Dr. Dre", 4.0),
new Student(7654325, "Joe Cool", 2.0)
};
return students;
}
}
/******************************************************************/
/******************************************************************/
class Student
{
private int number;
private String name;
private double gpa;
public Student(int snum, String sname, double sgpa)
{
this.number = snum;
this.name = sname;
this.gpa = sgpa;
}
public double getGPA()
{
return gpa;
}
public boolean isHonourStudent()
{
boolean isHonourStudent = false;
if(getGPA() >= 3.5)
{
isHonourStudent = true;
}
return isHonourStudent;
}
public boolean isFailing()
{
boolean isFailing = false;
if(getGPA() < 2.0)
{
isFailing = true;
}
return isFailing;
}
public String toString()
{
return number + " " + name + " " + gpa;
}
}
Here's the exception message:
java.lang.NullPointerException
at L2Q1.printStudents(L2Q1.java:41)
at L2Q1.process(L2Q1.java:28)
at L2Q1.main(L2Q1.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
The Problem
You are making elements in your students array null. Then you try to use toString() but on a null element. This is how it looks like: null.toString(), obviously that is bad.
Solution Without ArrayList
On the comments people suggested an ArrayList. I am assuming this is homework and you are forced to use an array, therefore you should do this:
Keep track of the size of the array. Use that to determine how many real elements, non-null elements, you have on the list. Like this:
for(int i = 0; i < arraySize; i++)
{
// Do something with the array here.
}
Make sure you declare arraySize as an instance variable.
private int arraySize = 0;
Remember you will need to increment arraySize for every new element and decrement it every time you null out an element.
Keep in mind that by the time your program finishes your array will have a trail of nulls at the end.
Hackish Solution
In the mean time you can do this to your printStudents() -- this is hackish and only a temporary fix.
public static void printStudents(Student[] students)
{
// Check if the array is null, good practice.
if(students == null)
return;
System.out.println("Students:");
for (int i = 0; i < students.length; i++)
{
// My hack: Check if element is null, if it is then skip it.
if(students[i] == null)
continue;
System.out.println(students[i].toString());
}
System.out.println();
}
This happens because you've already removed some of the students, turning them from Student to null. You're trying to call toString() on one of the non-existing students that are null.
I suggest you replace the array with ArrayList, from which you can actually remove elements. Alternatively, you can rebuild the array when you remove a student.
You are setting a Student object at an index to null, then later in a different method attempting to call toString() on a null object. Using List would help you work with this problem much more elegantly.
Without rewriting the whole code, here is how you could implement List instead:
public static void process() {
List<Student> students = new ArrayList<Student>();
List<Student> newStudents = new ArrayList<Student>();
...
Then when you loop through a List in all your different functions, you would use
for (int count = 0; count < students.size(); count++) {
//do stuff here
}
If you want to remove a student from a list, use
students.remove(count);
To populate the list, use
Student student1 = new Student(7654321, "Lara Zhivago", 3.75);
students.add(student1);
....