I have an array of objects that I am trying to add new objects to the first available 'null' location in the array. However, I am running into a runtime error whenever I attempt to add an object to the array. The error is :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -211
at Pokedex.addPokemon(Pokedex.java:37)
at Project4.main(Project4.java:36)
The questionable code in the Pokedex class is:
public void addPokemon(Pokemon pkm){
int blankSpace = 0;
for (int i = 0; i < billsPC.length; i++){
if(billsPC[i] == pkm)
System.out.println("Your Pokedex is already storing that Pokemon!");
else{
for(int j = 0; j < billsPC.length; j++){
if(billsPC[j] == null)
blankSpace++;
}
if(blankSpace == 0)
System.out.println("Your Pokedex is already holding the max amount!");
}
}
int dexLoc;
if (blankSpace == billsPC.length)
dexLoc = 0;
else
dexLoc = billsPC.length - blankSpace - 1;
//Line 37 is below
billsPC[dexLoc] = pkm;
}
The questionable code from the Project4 class (line 36) is:
kantoDex.addPokemon(pkm);
where pkm is a set Pokemon object and kantoDex is a set Pokedex object.
The main problem is the nested loops. They cause blankSpace to increment too many times. As such billsPC.length - blankSpace - 1 becomes a number much lesser than 0.
The answer to your question is yes, variables can be used as the array index in Java.
I suspect this method might perform what you want:
public boolean addPokemon(Pokemon pkm) {
for (int i = 0; i < billsPC.length; i++) {
if (billsPC[i] == pkm) {
System.out.println("Your Pokedex is already storing that Pokemon!");
return false;
}
if (billsPC[i] == null) {
for (int j = i + 1; j < billsPC.length; j++) {
if (billsPC[j] == pkm) {
System.out.println("Your Pokedex is already storing that Pokemon!");
return false;
}
}
billsPC[i] = pkm;
return true;
}
}
System.out.println("Your Pokedex is already holding the max amount!");
return false;
}
The method will add pkm to the first nullelement of billsPC should such an element exist. If billsPC already contains pkm or no null element, it will print a message. Finally, it will return true if and only if pkm was successfully added to billsPC, else false.
Yes it can, indeed you are using it before (billsPC[i]).
The problem in your code, as the exception suggests, is that you are trying to access an array location out of bounds, in this case with index -211.
Can a variable be used as the array index in Java? yes but it should be in the bounds of array. billsPC[-1] = pkm;//wrong
Related
I'm doing a little google interview question. Find the pair of numbers in a loop that add up to the number given. I found the numbers 2 and 6 that make up 8 so I say match = true so that the while loop stops, however it still proceeds until it finds the second which is 6 and 2 however, those numbers I have already found just the other way around and I had expected my loop to break as my if statement states if there is any 2 numbers that give the sum, match = true therefore terminating the loop, I guess I am wrong though.
However, if I get rid of the while statement and just return; once a match is found it breaks without looking for the second match (which I want it to).
Why is this happening, the logic of both seems the exact same to me.
Using the while(condition) Method
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
boolean match = false;
int sumNeeded = 8;
while(!match){
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j >= 0; j --){
if(list[i] != list[j]){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
match = true;
}
}
}
}
}
}
}
Using return
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
int sumNeeded = 8;
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j >= 0; j --){
if(list[i] != list[j]){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
return;
}
}
}
}
}
}
In your while-loop implementation, if the array doesn't have the desired pair at all it would result in an infinite loop. There is no need for the while statement in your solution.
After you enter into the while loop, you look for all the possible pairs in the array and then check for their sum. If it equals the desired sum, you make the boolean variable match as true.
But, until the nested for loop is completely executed (i.e., all the possible pairs are checked) we do not check for the while condition. The entire nested for loop is executed in one iteration of the while loop. Then, the while loop condition is checked again.
As by the end of the first iteration of the while loop all the possible pairs are accounted for, there is no need for a while loop.
Moreover, there are other logical errors in your implementation. The correct brute-force implementation is as follows:
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
boolean match = false;
int sumNeeded = 8;
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j > i; j --){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
return;
}
}
}
}
}
The inner-for loop is modified to reduce the double-counting of the unordered pairs. Whenever a match is found and printed, we exit the function.
You may also add a break statement inside the while loop in your initial implementation.
if(match == true) {
break;
}
The while condition continues to execute the first and second for-loop until it's finished where as with return it stops execution entirely from the first and second loop.
To fix the while loop you could use a label and then break from that.
firstLoop:
for(int i = 0; i < list.length; i ++) {
match = true;
break firstLoop;
This is an assignment we have and I'm a little bit lost with his directions. He tells us to write a program with a method called equals to compare the salary of EVERY TWO EMPLOYEES in the array (I've already created this) and prints the SSN of every two employees that have the same salary in pairs. He made a disclaimer that
the code should only compare two different employees and only once. Every two different employees are compared only once. The array is size 10.
I've already asked multiple peers on what he meant but they are also confused. This is what I have:
For the Class:
public boolean equals(Employee e)
{
boolean status;
if(salary == e.getSalary())
{
status = true;
}
else
status = false;
return status;
}
For the Demo:
for(int i = 0; i < employees.length; i++)
{
for(int j = i+1; j < employees.length; j++)
{
if(employees[i].equals(employees[j]))
System.out.println(employees[i].getSsn() + "\t" +
employees[j].getSsn());
}
}
It compiles, however it skips comparing index 0 and index 1. Any help is appreciated.
Initialize j with int j = i+1 instead of int j = i+2
This method is supposed to return true if there is more than one 1 in a column of a 2D array, yet it doesn't work. I can't figure out what's wrong with it so I thought I'd get some expert opinions.
Example:
10010
01001
10100
will return true because there are 2 ones in the first column.
Here is the code
public static boolean isVert(int[][] x) { //checks for more than one 1 in columns
int count = 0;
boolean break2 = false;
boolean check = false; //false means no 2 (or more) queens in same column
for (int i = 0; i < x.length; i++) {
count = 0;
for (int j = 0; j < x[i].length; j++) {
if (x[i][j] == 1) {
count++;
}
if (count > 1) {
break2 = true;
check = true;
break;
}
}
if (break2) {
break;
}
}
return check;
}
You break at the first occurance of 1 in whole array, which is probably not the expected result.
Explanation of how your code works:
loop until counter i is less than length of array (number of rows in array)
loop until counter j is less than length of i-th row (number of columns or elements in array)
check if element on i-th row and j-th column is 1, if true, increase variable count by one
if count is greater than 1 (this means it has to be 2 or greater) set break2 and check to true, break
if break2 is true (which is as count is > 2 and first loop breaks), break this loop too:
this happens in 1st row of your example table
end of loops, return check (which is true because 1st row contains 2 ones)
The problem in your code is that you break when you find your first row that satisfies your condition, but you do not (necessarily) check all the rows in given array.
I have corrected the code for you, hopefully it works (untested)
public static boolean isVert(int[][] x) { //checks for more than one 1 in columns
int count = 0;
for (int i = 0; i < x.length; i++) {
int rowCount = 0;
for (int j = 0; j < x[i].length; j++) {
if (x[i][j] == 1) {
rowCount++;
}
if(rowCount > 1) {
count++;
break;
}
}
}
// returns true if count of lines containing 1 equals length of array,
// if not, returns false
return count == x.length;
}
Start of by improving your naming convention. Your code has many variables named by their contents, instead of named by how they are used. For example:
boolean check = false; // false means no two queens in the same column.
instead of
boolean twoQueensInColumn = false;
and the other example
boolean break2 = false;
instead of the more reasonable
boolean continueLooking = true;
Plus, it is a very good idea to avoid using variables as place holders for loop escaping logic. For example, the two stanzas
...
if (count > 1) {
break2 = true;
check = true;
break;
}
}
if (break2) {
break;
}
are a breeding ground for bugs, requiring a lot of debugging to ensure they work "right now" which will break just as soon as you modify the code. Much better would be
boolean keepLooking = false;
for (int row = 0; keepLooking && (row < board.length); row++) {
int queensInColumn = 0;
for (int column = 0; keepLooking && (column < board[row].length, column++) {
if (board[row][column] != 0) {
queensInColumn++;
}
if (queensInColumn > 1) {
keepLooking = false;
}
}
}
The main difference being the control logic is in the loop "conditional" block, where it belongs.
I would recommend turning your integers to string and using the .contains() method and looping through that. This would make the code easier to understand.
I have been working on a project for way to long now and I am running into a nullpointerexception. I understand that it is when an object is pointing to nothing. I am getting this error while doing a bubble sort in Java. I can't figure out what is causing this exception and thus can't resolve it. The purpose of this code is to sort an array of student ID numbers in a specific order, I've chosen descending order.
public static void idNumber()
{
String[] iD = new String[150]; //array for ID Numbers
//System.out.println("Original order");
for(int i = 0; i < nNumStudents; i++) //add ID numbers to array iD
{
iD[i] = srStudents[i].getStudentKey();
//System.out.println(srStudents[i].getStudentKey());
}
//bubble sort
int k =0;
int j =0;
boolean exchange = true;
String temp;
temp = new String();
while ((k < iD.length - 1) && exchange)
{
exchange = false;
k++;
for(j = 0; j < iD.length - k; j++)
{
if(iD[j].compareTo(iD[j + 1]) > 0)
{
temp = iD[j];
iD[j] = iD[j + 1];
iD[j + 1] = temp;
exchange = true;
}
}
}
System.out.println(iD);
}
Exception in thread "main" java.lang.NullPointerException
at java.lang.String.compareTo(String.java:1139)
at StudentRegistrar.idNumber(StudentRegistrar.java:152)
at Sort.main(Sort.java:21)
From a glance at your code, my guess is that it is possible that your array size exceeds the number of students. If this is the case, you are attempting to compare empty slots in the array, which would give a null pointer exception. To fix this, increment to nNumStudents rather than to the full length of the array.
This nullpointer is coming up because all the members of String array String[] iD = new String[150]; are not initialize for example the for loop which is populating this iD array is either not running until 150 or one of its members is initialized with null so
First thing print and check what is the value of nNumStudents it should be 150. Then make sure that every value which is assigned to iD array is a non null value you can do this by modifying your code to print all the values it is assigned to
for(int i = 0; i < nNumStudents; i++) //add ID numbers to array iD
{
iD[i] = srStudents[i].getStudentKey();
//uncomment the below line and see if it doesn't print null
System.out.println(srStudents[i].getStudentKey());
}
if it exceeds 150 then you will get an ArrayIndexoutofbound exception not null pointer
I'm brand new to Java and my first assignment was to implement a "for" loop. I wrote this program in C++ and it compiles in Java, but I got an error at runtime. Can anyone tell me what's wrong?
import java.util.Scanner;
import java.util.Vector;
public class GlobalMembersMain
{
public static Vector<Integer> get_prime_factors(int number)
{
Vector<Integer> primefactors = new Vector<Integer>();
for (int j = 2; j <= number; j++)
{
if (number % j == 0)
{
primefactors.add(j);
number = number / j;
j = 1;
}
}
return primefactors;
}
public static void main(String[] args)
{
int number;
int count = 1;
System.out.print("Enter integer to analyse:");
System.out.print("\n");
Scanner scan = new Scanner(System.in);
number = scan.nextInt();
Vector<Integer> primefactors = new Vector<Integer>();
primefactors = get_prime_factors(number);
System.out.print("Prime factors are ");
for (int a = 0; a < primefactors.size() + 1; a++)
{
if (primefactors.elementAt(a) == primefactors.elementAt(a+1))
{
count++;
}
else
{
System.out.print(primefactors.elementAt(a));
System.out.print(" (");
System.out.print(count);
System.out.print(") ");
count = 1;
}
}
System.out.print("\n");
}
}
The output:
Enter integer to analyse:
10
Prime factors are 2 (1) Exception in thread "main" java.lang.ArrayIndexOutOfBoun
dsException: 2 >= 2
at java.util.Vector.elementAt(Unknown Source)
at GlobalMembersMain.main(GlobalMembersMain.java:36)
for (int a = 0; a < primefactors.size() + 1; a++)
{
if (primefactors.elementAt(a) == primefactors.elementAt(a+1))
{
count++;
}
Is exceeding the size of the primefactors collection. By 2, in fact.
Change to primefactors.size() - 1 to avoid this error.
Arrays are zero based, which I imagine you are aware of. What you may not be aware of is that in Java a List is backed by an array as well. When you invoke primefactors.size() +1 you are getting one more than you would possibly want. For instance is pf is of size 1 your loop will do the following:
pf.get(0); //returns the only value in the list
pf.get(1); // element doesn't exist
Now the other thing is you do not want to use Vector, generally speaking in Java. It is a synchronized collection. What you want is List/ArrayList.
OTHER CODE ISSUES
public static Vector<Integer> get_prime_factors(int number)
this does not need to be static. Also naming convention is camel case in Java so your function name should be getPrimeFactors(int number)
GlobalMembersMain
Should most likely be named GlobalMember as classes are to be singular in nature and I believe you added Main to indicate it was the class that holds the main function.
In your main function you would do this:
GlobalMember member = new GlobalMember();
member.getPrimeFactors(number);
This is where the problem is:
for (int a = 0; a < primefactors.size() + 1; a++)
{
if (primefactors.elementAt(a) == primefactors.elementAt(a+1))
{
count++;
}
//...
primefactors.elementAt(a+1) for the last element in your collection will throw the exception (AIOB).
Remember that arrays, lists and vectors in Java are zero-based. In your case, the primefactors vector will consist of two elements, available at index 0 and 1 respectively.
The problem you are facing is that you try to access the element primefactors.elementAt(2) which does not exist.
One problem is the break condition in the loop:
for (int a = 0; a < primefactors.size() + 1; a++) {
// ...
}
The first time, a will be 0, the second time 1 which are both fine. However, the loop will not break the third time, because a will equal 2, which is less than primefactors.size() + 1. Consequently, there will be a call to primefactors.elementAt(2) which does not exist and the program will blow up.
There is also a second problem inside the loop since you increment the loop variable by one during the comparison:
if (primefactors.elementAt(a) == primefactors.elementAt(a+1)) {
// ...
}
Yet again, your program will fail if you pass 2 as an argument to primefactors.elementAt(...)