Java code with tests - infinite loop? - java

I try to get the relationship between people. However, when I run unit test, the test runs forever, it doesn't get the result and my CPU usage was high.
Could someone see what's wrong with my code?
The string relations are multiple line inputs of string with in the format of "A , B C , D" where A is the parent of B and C is the parent of D.
This is the default constructor for the code and the input in string format. We don't need to check if the format is correct:
public SeeRelations(String relations){
this.relations = relations;
}
This the helper function to get each line of the string from the formatted input:
//helper function to get each line of the string
private ArrayList<String> lineRelations(){
int i;
ArrayList<String> lineRelations = new ArrayList<String>();
String[] lines = relations.split("\n");
for(i = 0; i < lines.length; i++){
lineRelations.add(lines[i]);
}
return lineRelations;
}
This is the function to put all the relations from the input formatted string to arraylists:
//helper function to put each of the relationship in arraylists
private ArrayList<ArrayList<String>> allRelations(){
int i;
ArrayList<ArrayList<String>> allRelations = new ArrayList<ArrayList<String>>();
ArrayList<String> lineRelations = lineRelations();
for(i = 0; i < lineRelations.size(); i++){
ArrayList<String> eachLine = new ArrayList<String>(Arrays.asList(lineRelations.get(i).split("\\s*,\\s*")));
allRelations.add(eachLine);
}
return allRelations;
}
This is the method to check if the input name exists:
//helper function to see if the name exist for seeRelations()
private boolean hasThisName(String name){
ArrayList<ArrayList<String>> allRelations = allRelations();
int i;
int j;
for(i = 0; i < allRelations.size(); i++){
for(j = 0; j < allRelations.get(i).size(); j++){
if(name.equals(allRelations.get(i).get(j))){
return true;
}
}
}
return false;
}
This is the function to get the generation number between two people:
//helper function to get Generation number of seeRelations()
private int getGenerationNum(String person, String ancestor){
ArrayList<ArrayList<String>> allRelations = allRelations();
String name;
int i;
int j;
int generationNum = 0;
for(i = 0, j = 0, name = ancestor; i < allRelations.size(); i++){
if(name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))){
generationNum++;
ancestor = allRelations.get(i).get(1);
i = 0;
j = 1;
}
else if(ancestor.equals(allRelations.get(i).get(0)) && person.equals(allRelations.get(i).get(1))){
generationNum++;
j = 1;
break;
}
}
if(j == 0){
return 0;
}
else{
return generationNum;
}
}
This is the method to get multiple of "great" for the final output:
private String great(int num){
int i;
String great = "";
for(i = 0; i < num; i++){
great += "great";
}
return great;
}
This is my final method to check the relationship between two people:
public String SeeRelations(String person, String ancestor){
int generationNum = getGenerationNum(person, ancestor);
String great = great(generationNum - 2);
if(!(hasThisName(person) && hasThisName(ancestor))){
return null;
}
else{
if(generationNum == 0){
return null;
}
else if(generationNum == 1){
return ancestor + " is the parent of " + person;
}
else if(generationNum == 2){
return ancestor + " is the grandparent of " + person;
}
else{
return ancestor + " is the" + " " + great +"grandparent of " + person;
}
}
}
This is my test cases, And it runs forever and couldn't get a result
public class FamilyTreeTest {
#Test
public void testSeeRelations() {
FamilyTree relation2 = new FamilyTree("John Doe , Mary Smith" + "\n" + "Martin Weasel , John Doe");
assertEquals("Martin Weasel is the grandparent of Mary Smith", familyTree2.SeeRelations("Mary Smith", "Martin Weasel"));
}

for(i = 0, j = 0, name = ancestor; i < allRelations.size(); i++){
if(name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))){
generationNum++;
ancestor = allRelations.get(i).get(1);
i = 0;
j = 1;
}
else if(ancestor.equals(allRelations.get(i).get(0)) && person.equals(allRelations.get(i).get(1))){
generationNum++;
j = 1;
break;
}
}
here you have your faulty lines
in your case your ancestor/name is "Martin Weasel" given relation for martin is "John Doe", but you are looking for mary smith so name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))) this is true and this i = 0; makes your loop starts from beginning
what you could do, try to create object person
ie
class Person{
String name;
List childrens;
List parents;
...
}
then just do simple tree walker
int SearchDown(Person person, String searchedRelation,int generation)
{
if person.getName().equals(searchedRelation())
return generation;
for (Person child: person.getChildren())
{
int generation = SearchDown(child, searchedRelation, generation+1);
if (generation!=-1) return generation;
}
return -1;
}
etc...
i'm really finding this way much easier to deal with all types of trees

Related

Add Two Polynomials Java Program

I am working on this simple program that adds two polynomials. However, I am getting wrong results and could not spot the mistake.
import java.util.LinkedList;
public class Polynomial {
private LinkedList<Term> terms = new LinkedList<Term>();
private class Term {
private int coef;
private int exp;
public Term(int coef, int exp) {
this.coef = coef;
this.exp = exp;
}
public int getCoef() {
return coef;
}
public int getExp() {
return exp;
}
public String toString() {
return (this.coef + "x^" + this.exp);
}
}
public String addPoly(String first, String second) {
LinkedList<Term> otherTerms = new LinkedList<Term>();
String result = "";
String [] termsArray1 = first.split(";");
String [] termsArray2 = second.split(";");
for (int i = 0; i < termsArray1.length; i++) {
String [] temp = termsArray1[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
terms.add(currentTerm);
}
for (int i = 0; i < termsArray2.length; i++) {
String [] temp = termsArray2[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
otherTerms.add(currentTerm);
}
int i = 0;
int j = 0;
while (true){
if(i == terms.size() || j == otherTerms.size()) {
break;
}
if(terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
if(terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
result = result.substring(0, result.length()-1);
return result;
}
}
::Test::
String s3 = "5x^2;-4x^1;3x^0";
String s4 = "6x^4;-1x^3;3x^2";
Polynomial p = new Polynomial();
System.out.println(p.addPoly(s4, s3));
Expected result: 6x^4;-1x^3;7x^2;-4x^1;3x^0
Actual result: 3x^4;7x^2;-1x^1;10x^0
The problem is that when your loop exits, one of the following can still be true:
i < terms.size()
j < j == otherTerms.size()
And this is the case with your example input. This means that part of one of the terms has not been processed and integrated into the output.
A second problem is that your multiple if statements are not exclusive; after the first if block is executed and j++ has executed, it might well be that j is an invalid index in otherTerms when the second if is evaluated. This should be avoided by turning the second and third if into else if.
Here is a fix for that loop:
while (i < terms.size() || j < otherTerms.size()) {
if(i == terms.size() || j < otherTerms.size() && terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
else if(j == otherTerms.size() || i < terms.size() && terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
else if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
Better approach
Your approach is not really OOP. Ideally, the first expression should serve to create one instance of Polynomial and the other expression should serve to create another instance of Polynomial. Then there should be a method that can add another Polynomial instance to the own instance. Finally there should be a toString method that returns the instance as a string in the required format. Your driver code would then look like this:
Polynomial a = new Polynomial("5x^2;-4x^1;3x^0");
Polynomial b = new Polynomial("6x^4;-1x^3;3x^2");
Polynomial sum = a.addPoly(b);
System.out.println(sum.toString());
This is much more object oriented, and will automatically avoid the code repetition that you currently have.

For Loops and string comparisons

I am reworking a class problem on For Loops and cannot gain a total out of a running score. I attempted to use the string comparisons, but that may be where the problem is. The assignment is:
"Simon Says" is a memory game where "Simon" outputs a sequence of 10 characters (R, G, B, Y) and the user must repeat the sequence. Create a for loop that compares the two strings starting from index 0. For each match, add one point to userScore. Upon a mismatch, exit the loop using a break statement. Ex: The following patterns yield a userScore of 4:
simonPattern: RRGBRYYBGY
userPattern: RRGBBRYBGY
import java.util.Scanner;
public class SimonSays {
public static void main (String [] args) {
String simonPattern = "";
String userPattern = "";
int userScore = 0;
int i = 0;
userScore = 0;
simonPattern = "RRGBRYYBGY";
userPattern = "RRGBBRYBGY";
/* Your solution begins here */
String ss1 = simonPattern.substring(0, 2);
String us1 = userPattern.substring(0, 2);
String ss2 = simonPattern.substring(2, 3);
String us2 = userPattern.substring(2, 3);
String ss3 = simonPattern.substring(4, 5);
String us3 = userPattern.substring(4, 5);
String ss4 = simonPattern.substring(6, 7);
String us4 = userPattern.substring(6, 7);
String ss5 = simonPattern.substring(8, 9);
String us5 = userPattern.substring(8, 9);
for (i = 0; i < simonPattern.length(); i++) {
if (ss1.equals(us1)) {
userScore = userScore + 1;
}
if (ss2.equals(us2)){
userScore = userScore + 1;
}
if (ss3.equals(us3)){
userScore = userScore + 1;
}
if (ss4.equals(us4)){
userScore = userScore + 1;
}
if (ss5.equals(us5)){
userScore = userScore + 1;
}
else{
break;
}
}
/* ^ Your solution goes here ^ */
System.out.println("userScore: " + userScore);
return;
}
}
your problem is in your for loop change if (ss1 == us1) to if (ss1.equals(us1)) same with the else if stucture because String is a reference type and not a primitive data type
primitive data types are int,double,long,float,byte,short,boolean,char and all objects are reference type
public static void main (String [] args)
{
String simonPattern = "";
String userPattern = "";
int userScore = 0;
userScore = 0;
simonPattern = "RRGBRYYBGY";
userPattern = "RRGBBRYBGY";
String[] simons = new String[5];
String[] users = new String[5];
int adder=2;
int location=0;
for(int i=0;i<simonPattern.length();i+=2)
{
simons[location]=simonPattern.substring(i,adder);
location++;
adder+=2;
}
adder=2;
location=0;
for(int i=0;i<userPattern.length();i+=2)
{
users[location]=userPattern.substring(i,adder);
location++;
adder+=2;
}
for (int i = 0; i < simonPattern.length(); i++)
{
if(users[i].equals(simons[i]))
userScore++;
}
System.out.println(userScore);
}
You might want to consider doing it by iterating through the userPattern instead like this:
int userScore = 0;
String simonPattern = "RRGBRYYBGY";
String userPattern = "RRGBBYYBGY";
for (int i = 0; i < userPattern.length(); i++) {
String p = userPattern.substring(0, 1 + i);
if (simonPattern.startsWith(p)) {
userScore = userScore + 1;
}
}
if (userScore < simonPattern.length()) {
System.out.println("You got " + userScore + " letters deep out of " +
simonPattern.length() + " before you made a mistake.");
}
else {
System.out.println("YOU WIN!");
}
You correctly changed the loop to iterate length of simonPattern. Now you just need to throw away the code inside the loop and actually use the iterator variable i.
To extract a single character from a string, you could continue to use substring(i, i+1) to get a String value, but for single characters it's better to use charAt(i).
Also, to increment a variable by 1, it's better to use userScore++, instead of userScore = userScore + 1, although that does work too.
This means that your code should be:
String simonPattern = "RRGBRYYBGY";
String userPattern = "RRGBBRYBGY";
int userScore = 0;
for (int i = 0; i < simonPattern.length(); i++) {
char c1 = simonPattern.charAt(i);
char c2 = userPattern.charAt(i);
if (c1 != c2)
break;
userScore++;
}
System.out.println("userScore: " + userScore); // prints 4

deleting an object from an array of objects in java

import java.util.StringTokenizer;
class Count {
int count;
String name;
void SetCount(int c, String n) {
this.count = c;
this.name = n;
}
void Show() {
System.out.print("Word= " + name);
System.out.print(" Count= " + count);
System.out.println();
}
}
class Contains2 extends Count {
public static void main(String args[]) {
String s = "Hello this program will repeat itself for this useless purpose and will not end until it repeats itself again and again and again so watch out";
int i, c2, j;
StringTokenizer st = new StringTokenizer(s, " ");
c2 = st.countTokens();
String[] test = new String[c2];
Count[] c = new Count[c2];
for (i = 0; i < c2; i++) {
c[i] = new Count();
}
i = 0;
while (st.hasMoreTokens()) {
String token = st.nextToken();
test[i] = token;
c[i].SetCount(0, test[i]);
i++;
}
for (i = 0; i < c2; i++) {
for (j = 0; j < c2; j++) {
if (c[i].name.equals(test[j]))
c[i].count += 1;
}
}
for (i = 0; i < c2; i++) {
c[i].Show();
}
}
}
so i made this small program to count the number every word was repeated in a paragraph. its working as planned but now i am getting duplicates of every word since i made separate objects for each and printing them all. so is there any way i could delete the duplicate words i mean deleting those objects based on their names. i can set them to null but it would still print them so i just wanna get rid of them or skip them somehow
You cannot adjust the size of a array once it's created. You could only create a new array with a different size and copy the non-null elements.
You could also set elements to null and just ignore those elements for printing...
for (i = 0; i < c2; i++) {
if (c[i] != null)
c[i].Show();
}
An alternative would be using a List, which allows you to remove elements.
Alternatively a Map<String, Integer> mapping from a word to the count could be used. In this case you don't even need the Count class:
String s = "Hello this program will repeat itself for this useless purpose and will not end until it repeats itself again and again and again so watch out";
StringTokenizer st = new StringTokenizer(s, " ");
Map<String, Integer> map = new HashMap<>();
while (st.hasMoreTokens()) {
map.merge(st.nextToken(), 1, Integer::sum);
}
for (Map.Entry<String, Integer> e : map.entrySet()) {
System.out.print("Word= " + e.getKey());
System.out.print(" Count= " + e.getValue());
System.out.println();
}

Why is my serial number system repeating the number 001?

I'm trying to assign a unique ID to my contacts list in Java. It works fine except for the first number. It always repeats ID001 twice before moving on to ID002. Any Idea why?
private static String getSN() {
String SN = "ID001";
for (int i = 0; i < AddressBook.size(); i++) {
if(AddressBook.size()<10){
if (AddressBook.get(i).substring(0, 4).contains("ID00"+i));
int snString = i+1;
SN = "ID00"+Integer.toString(snString);
if(SN.equals("ID0010")){
SN = ("ID010");
}
}
else{
if(AddressBook.size()<100){
if (AddressBook.get(i).substring(0, 5).equals("ID0"+i));
int snString = i+1;
SN = "ID0"+Integer.toString(snString);
if(SN.equals("ID00100")){
SN = ("ID0100");
}
}
}
}
return SN;
}
Why is my serial number system repeating the number 001?
Because SN is a local variable. A local variable in a static method is still a local variable, and it disappears each time a call to the method returns.
You probably should be using a static field ... declared in the enclosing class.
I figured out a much simpler way to do things. Instead of using a loop, every time I add a new person to my contact list I will ad a serial number.
private static void setSN() {
if (AddressBook.size() < 10) {
for (int i = 0; i < AddressBook.size(); i++) {
String tempString = AddressBook.get(i);
if (tempString.contains("ID00" + Integer.toString(AddressBook.size() + 1))) {
SN = "ID00" + Integer.toString(AddressBook.size() + 2);
}
else{
SN = "ID00" + Integer.toString(AddressBook.size() + 1);
}
}
}
else {
if (AddressBook.size() < 100) {
for (int i = 0; i < AddressBook.size(); i++) {
String tempString = AddressBook.get(i);
if (tempString.contains("ID0" + Integer.toString(AddressBook.size() + 1))) {
SN = "ID0" + Integer.toString(AddressBook.size() + 2);
}
else{
SN = "ID0" + Integer.toString(AddressBook.size() + 1);
}
}
}
}
}
Try this:
1. Modify AddressBook.get(i).substring(0, 4).contains("ID00"+i) by
AddressBook.get(i).substring(0, 5).contains("ID00"+(i+1))
2. Modify int snString = i+1; by
int snString = i+2;
3. This is because the index of the list starts at 0.
private static String getSN() {
String SN = "ID001";
for (int i = 0; i < AddressBook.size(); i++) {
if(AddressBook.size()<10){
if (AddressBook.get(i).substring(0, 5).contains("ID00"+(i+1))){
int snString = i+2;
SN = "ID00"+Integer.toString(snString);
}
if(SN.equals("ID0010")){
SN = ("ID010");
}
} else {
if(AddressBook.size()<100){
if (AddressBook.get(i).substring(0, 5).equals("ID0"+(i+1))) {
int snString = i+2;
SN = "ID0"+Integer.toString(snString);
}
if(SN.equals("ID00100")){
SN = ("ID0100");
}
}
}
}
return SN;
}

NPE in line invoking equals()

Sorry if this all seems hard to understand but I am new to programming and I have looked in several books and websites and from my understanding what I am trying to do should work. The assignment I am working on is classes calling classes. Without putting all my code in here I will try to be as specific as possible in unclear areas. The null pointer exception is for this particular line of code:
if(CDList[i].getArtist().equals(artist) == true)
//CDList is an array of CD objects (which are created in another class)
//getArtist() is a method of the CD class which returns a String
//the artist in the equals() is the Scanner object the user has inputed, also a String
The point of this particular method is to search through the array CDList and compare the artist String stored to the artist String scanned in and then the same for the title. If found then the contents of that portion of the array will be deleted. Here is the rest of the method if it will help:
void delete()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter artist and title to be deleted: ");
String artist = input.nextLine();
String title = input.nextLine();
for(int i = 0; i <= numOfCDs; i++)
{
if(CDList[i].getArtist().equals(artist) == true)
{
for(int j = 0; j <= numOfCDs; j++)
{
if(CDList[j].getTitle().equals(title) == true)
{
System.out.println("Found CD: " + CDList[j].getArtist() + " " +
CDList[j].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[j] = null;
numOfCDs--;
}
}
else
System.out.println("CD not found.");
}
}
else
System.out.println("CD not found.");
}
}
Sorry, here is the rest of the code. Just thought it was so much I'd leave it out.
CD Class:
package assignment3;
public class CD
{
public String artist;
public String title;
private tracklist listOfTracks = new tracklist();
CD(String artistName, String titleName)
{
artist = artistName;
title = titleName;
}
public String getArtist()
{
return artist;
}
public String getTitle()
{
return title;
}
public boolean addTrack(String trackInfo)
{
boolean result = false;
if(listOfTracks.add(trackInfo) == true)
result = true;
return result;
}
public int numTracks()
{
int count = listOfTracks.count();
return count;
}
public void display()
{
System.out.println(" ");
System.out.println(getArtist() + " : " + getTitle());
listOfTracks.display(7);
}
}
trackList Class:
package assignment3;
public class tracklist
{
public String[] tracks;
public int numElements;
tracklist()
{
tracks = new String[99];
numElements = 0;
}
public boolean add(String track)
{
boolean result = true;
int index = 0;
while(tracks[index] != null)
{
index++;
}
tracks[index] = track;
numElements++;
if(numElements > 99)
result = false;
return result;
}
public int count()
{
return numElements;
}
public void display(int indent)
{
for(int i = 1; i < numElements; i++)
{
System.out.print(i);
if(i >= 10)
{
for(int j = 0; j < (indent - 1); j++)
{
System.out.print(" ");
}
}
else
{
for(int j = 0; j < indent; j++)
{
System.out.print(" ");
}
}
System.out.println(tracks[i]);
}
}
}
CDList Class:
package assignment3;
import java.util.Scanner;
public class CDList
{
public int numOfCDs;
private CD[] CDList;
private int front,rear;
CDList(int size)
{
CDList = new CD[size];
numOfCDs = 0;
front = 0;
rear = size - 1;
}
boolean add()
{
boolean result;
Scanner input = new Scanner(System.in);
System.out.println("Enter the Artist Name and CD Title: ");
CD userCD = new CD(input.nextLine(), input.nextLine());
System.out.println("Enter the number of tracks: ");
int trackNumber = input.nextInt();
System.out.println("Enter your track titles: ");
for(int i = 0; i <= trackNumber; i++)
{
userCD.addTrack(input.nextLine());
}
if(rear == front)
result = false;
else
{
if(CDList[rear] != null)
rear--;
else
CDList[rear] = userCD;
result = true;
}
return result;
}
void delete()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter artist and title to be deleted: ");
String artist = input.nextLine();
String title = input.nextLine();
for(int i = 0; i <= CDList.length - 1; i++)
{
if((CDList[i].getArtist().equals(artist)) &&
(CDList[i].getTitle().equals(title)))
{
System.out.println("Found CD of: " + CDList[i].getArtist() + " " +
CDList[i].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[i] = null;
numOfCDs--;
}
}
else
System.out.println("CD not found.");
}
}
void SortArtist()
{
CD temp = new CD(" ", " ");
for(int i = 0; i < numOfCDs; i++)
if(CDList[i].getArtist().compareTo(CDList[i + 1].getArtist()) < 0)
{
temp = CDList[i];
CDList[i] = CDList[i + 1];
CDList[i + 1] = temp;
}
}
void SortTitle()
{
CD temp = new CD(" ", " ");
for(int i = numOfCDs; i > 0; i--)
{
int x = 0;
for(int j = 1; j <= i; j++)
{
if(CDList[i].getTitle().compareTo(CDList[i + 1].getTitle()) < 0)
x = j;
}
temp = CDList[x];
CDList[x] = CDList[i];
CDList[i] = temp;
}
}
void Display()
{
for(int i = 0; i <= numOfCDs; i++)
{
while(CDList[i] == null)
i++;
CDList[i].display();
}
}
int size()
{
return numOfCDs;
}
}
if(CDList[i].getArtist().equals(artist) == true)
If you are getting NPE, here are the possibilities:
CDList is null
CDList[i] is null
CDLIst[i].getArtist() returns null
Class Artist overrides equals() and has a bug that results in NPE, but in that case the NPE would point to a statement in equals().
You haven't shown the class Artist so we can see if it overrides equals(), and haven't posted the stack trace so we can see exactly where the exception is thrown.
As others have commented, the == true is superfluous.
I would recommend using a LinkedList<CD> or ArrayList<CD> instead of CD[].
This will allow you to easily remove items, like so:
LinkedList<CD> cdList = new LinkedList<CD>();
// add items with cdList.add(...);
Iterator<CD> cdListIterator = cdList.iterator();
// Loop while the list still contains elements.
while (cdListIterator.hasNext()) {
CD thisCd = iterator.next();
// do some operation on the cd to tell whether you want to delete it
// for example:
if (thisCd.getArtist().equals(artist) && thisCd.getTitle().equals(title)) {
iterator.remove(); // it's that simple
// Don't have to mess with `cdCount--` or anything.
}
}
And, as some have commented, you don't need a.equals(b) == true; you can just use a.equals(b).
there's nothing wrong with if condition. Its your loop that has the problem.
Use a single for loop:
for(int i = 0; i <= numOfCDs; i++)
{
if(CDList[i].getArtist().equals(artist) && CDList[i].getTitle().equals(title))
{
System.out.println("Found CD: " + CDList[j].getArtist() + " " + CDList[j].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[i] = null;
// do not do numOfCDs-- here
}
}
}
There are a number of problems here.
The immediate cause of your NPE is that the inner loop "removes" a CD from the list by assigning it to null, and then the outer loop tries to test the CD at the position you just removed. Since it is null, you then attempt to call null.getArtist() which NPEs.
The first thing to note is that you only need one loop. The loop body should test that the CD you are looking at has the same title AND artist ...
The next thing to note is that getting rid of the extra loop is not enough. If the delete() method is called more than once, the second call is likely to encounter a null entry that was produced by the first call ... and you will get an NPE as before. The tests should check for a null before they try to get the title / artist information; e.g.
CD cd = cdList[i];
if (cd != null &&
cd.getArtist().equals(artist) &&
cd.getTitle().equals(title)) {
// ...
}
At this point a design problem becomes apparent. These null values in the array are a bad idea. There are three fixes:
You could remove the CDs by creating a new array one element smaller ... and copy across all CDs apart from the one you are deleting.
You could add a cdListSize field, and arrange that it gives you the number of valid entries in the list. Then (and this is the important bit), when you delete an entry from the list, move the current last entry to the place where the deleted entry was and decrement the cdListSize. If you do that consistently, the null entries will all be at the end, and you can iterate from zero to cdListSize - 1 to get the non-null entries.
Best of all, use a List rather than an array to represent the CD list. The List API provides a method for removing the entry at a given position. The method really removes it ... it doesn't just set it to null.
Finally, you may need to take a step back and look at the larger application. Is the CD list supposed to be persisted; e.g. so that it is still available when your application restarts? Is it likely to be large; e.g. too large to fit into memory? Are you likely to want to do complicated queries on the CD list? All of these things would suggest that you should use a database rather than an in-memory data structure.
(However, with the extra code you've just added, it is clear that would be beyond the scope of your assignment.)
Found it! Thank ya'll for your comments, I did make some changes that ya'll recommended. The issue was with the CDList[i] being null. Just implemented a if(CDList[i] == null) then continue; Thank ya'll for your input. –

Categories

Resources