This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I've been writing a simple JFrame program to solve basic math equations, the program takes 5 values, up to two of which may be null, identifies the correct equation and calculates the null values. This section of code below takes the 5 values in a hashmap, identified by a string (V,U,S,A,T), identifies which ones are null and adds them to a seperate array (nullvalues), which is then iterated through (nullValueLoop) to identify a suitable equation and solve the unknown.
The problem arises in nullValueLoop, it only appears to iterate once, stopping abruptly after the first iteration.
I've added a lot of system.out's while trying to debug this, and have included the console output to hopefully show whats going on. The exception called is from another class (as the program continues) attempting to call the second null value and finding it to be null.
Hopefully i've explained this well, any help is much appreciated.
public void calculate() {
// Stores the keys to reference the null values in HashMap<Double> values;
ArrayList<String> nullvalues = new ArrayList<String>();
for(String tempKey : values.keySet()){
if(values.get(tempKey)==null){
nullvalues.add(tempKey);
System.out.print("Found null value " + tempKey + ", adding to array. \n");
}
}
System.out.print("Beginning loop of nullvalues, of size " + nullvalues.size() + "\n");
nullValueLoop:
for(String nullvalue : nullvalues){
System.out.print("Starting outerloop, iterating nullvalue " + nullvalue + "\n");
EquationLoop:
for(Equation e : registeredEquations){
// Flag to keep ` of if we have any unknowns yet
boolean foundUnknown = false;
// Iterate through the values required
// If the loop does not exit, the equation only requires one of our null values and the program continues.
for(String s : e.getRequiredChars()){
// If we have a null value and havent yet had one, all is good
if(nullvalues.contains(s) && foundUnknown == false){
foundUnknown = true;
// We have more than one null value, abort
} else if(foundUnknown == true && nullvalues.contains(s)){
continue EquationLoop;
}
}
System.out.print("Using equation " + e.getIdentifier() + "\n");
System.out.print("Found suitable equation.\n");
Double returnValue = e.calculate(values, nullvalue);
System.out.print("Calculated return value.\n");
values.put(nullvalue, returnValue);
nullvalues.remove(nullvalue);
System.out.print("Added new value to values array\n");
System.out.print("Calculated value " + nullvalue + " to " + values.get(nullvalue) + "\n");
break EquationLoop;
}
System.out.print("Ending outerloop iteration \n");
}
mainWindow.updateTextBoxes();
}
Console output:
Couldn't load value T | Assigning to null
Couldn't load value A | Assigning to null
Found null value T, adding to array.
Found null value A, adding to array.
Beginning loop of nullvalues, of size 2
Starting outerloop, iterating nullvalue T
Using equation 3
Found suitable equation.
Calculated return value.
Added new value to values array
Calculated value T to 10.0
Ending outerloop iteration
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at uk.co.ElliotPurvis.MainWindow.updateTextBoxes(MainWindow.java:143)
at uk.co.ElliotPurvis.Main.calculate(Main.java:136)
at uk.co.ElliotPurvis.MainWindow.actionPerformed(MainWindow.java:118)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
Process finished with exit code 0
Inside EquationLoop you are modifying the list nullvalues, which is being iterated over by the outer loop. This is undefined behavior, you are not allowed to modify a collection while iteration is in progress.
I'm surprised you didn't get ConcurrentModificationException instead.
Related
I have been asked from my professor to add an object in the middle of an ArrayedList<Employee> using listiterator.
I have tried doing in the following way first:
ListIterator < Employee > li = emps.listIterator(emps.size());
System.out.println("\nUsing ListIterator:\n");
i = 1;
while (li.hasPrevious()) {
if (li.nextIndex() == 5) {
li.add(emp_M);
}
System.out.println(" Employee " + (i++) + " " + li.previous());
}
But this produces a seemingly infinite number of iterations where li.nextIndex() gets stuck on 5.
I have verified this with the debugger and this happens only after li.add(emp_M) is evaluated.
I have found a solution where I added a break right after li.add(emp_M) and continued parsing the list separately in the same way but without adding to the list emp_M at all:
//parse in two loops to add the middle employee, without the break the list seemingly spirals into infinity!
System.out.println("\nUsing ListIterator:\n");
i = 1;
while (li.hasPrevious()) {
if (li.nextIndex() == 5) {
li.add(emp_M);
System.out.println("ADDED IN MIDDLE");
break;
}
System.out.println(" Employee " + (i++) + " " + li.previous());
}
while (li.hasPrevious()) {
System.out.println(" Employee " + (i++) + " " + li.previous());
}
This left me wondering, is what I did a lazy and naive approach? How else can I add to a list with listIterator?
The problem in your code is that you will add the element emp_M indefinitely.
If we go through one iteration where you add an element:
Suppose li.nextIndex() == 5, then you will add a new element to your iterator, and according to the documentation of add, you will also increase by one your index (hence you move your iterator to the right). Then your loops continues and you move your iterator to the left with li.previous(), which happens to be place before you added the element (and verifies the if condition to add).
Now, you start a new iteration of your while loop, verifies the condition again, add a new element ect... You will stay stuck at the element verifying the condition by adding indefinitely new elements.
To make the code easier, try to run your iterator in the documentation direction (ie e1 -> e2 -> e3 -> e4)
ListIterator < Employee > li = emps.listIterator();
i = 1;
while (li.hasNext()) {
if (li.nextIndex() == 5) {
li.add(emp_M);
}
System.out.println(" Employee " + (i++) + " " + li.next());
}
I have found it after digging deeper in the debugger.
At the moment before adding li.nextIndex() == 5 and li.previousIndex() == 4
After adding the object the aforementioned change to li.nextIndex() == 6 and li.previousIndex() == 5 this is because listIterator's .add() inserts the object before .next().
Moving ahead with this problem sets up a back and forth loop where li.previous() decreases both li.previousIndex() and li.nextIndex() by 1, and calling li.add(emp_M) increases both aforementioned values by 1.
To fix it, we need to skip the added element after adding:
System.out.println("\nUsing ListIterator:\n");
i = 1;
while (li.hasPrevious())
{
if(li.nextIndex() == 5)
{
li.add(emp_M);
li.previous();
System.out.println("ADDED IN MIDDLE");
// break;
}
System.out.println(" Employee " + (i++) + " " + li.previous());
}
this effectively negates the problem mentioned above.
Sometimes by simply asking a question you find the answer yourself!
I'm going to delay accepting my own answer if someone can explain it to me better than I understood it.
There is an array index out of bounds exception in my recursive function. Can someone try to point out to me why that is the case?
This line: return minChange(a, IntegerList); is having the array index out of bounds exception as well as most likely this line:
return minimumValue(1 + minChange(a - d, integerList), minChange(a, updatedList));
/* Function minChange: Minimum Change
Pseudo-code:
minChange(0, ds) = 0
minChange(a, []) = Failure
minChange(a, d :: ds) = minChange(a,ds) if d > a
minChange(a, d :: ds) = min(1 ++ minChange(a - d, d :: ds) otherwise
*/
public int minChange(int a, List<Integer> integerList) {
//int minimumResult = 0;
int indexNumber = 0;
int d = integerList.get(indexNumber); (line 246)
if(a == 0) {
// If a is 0 return 0
return 0;
} else if(integerList.isEmpty()) {
return -1;
} else if(d > a) {
integerList.remove(indexNumber); // Remove first element from list
// Recursive call to minChange
return minChange(a, integerList); (line 261)
} else {
// Create updatedList and remove first element
List<Integer> updatedList = integerList;
updatedList.remove(indexNumber);
indexNumber++;
return minimumValue(1 + minChange(a - d, integerList), minChange(a, updatedList)); (line 269)
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out-of-bounds for length 0
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:246)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:269)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:269)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:269)
How can I fix this array index out of bounds exception. It seems one line needs to be fixed. If so how can I fix this error? What are some ways?
Why it Fails:
A specific sequence of events that leads to the out of bounds exception would be, for example:
minChange(1, [4]) // goes into second-to-last (else if) case, since 4 > 1. 4 is then removed.
minChange(1, []) // crashes
It's not clear what your code was intended to do in this case, since your pseudo-code doesn't define minChange(a, ds).
Even if we stipulate that the input list has to have more than one item, we'll often hit this same case:
minChange(5,[4, 8])
minChange(1,[8])
minChange(1,[])
I'm not sure what you intended to happen here, but, anyway, there are other issues...
Bugs:
There is very likely a bug in your code with this line:
// this just creates another reference to the existing list
// https://stackoverflow.com/questions/6536094/java-arraylist-copy
// meaning: both recursive calls will operate on the same list
// even though one uses the "updatedList" reference and one uses "integerList"
List<Integer> updatedList = integerList;
Also, the use of indexNumber indicates a bug, since it's only ever used when it has value 0 - the incrementing is pointless. Remember that local variables in the function are getting 'reset' in each recursive call, unless you pass them as a parameter.
Debugging Strategies:
First, clarify what you actually want the algorithm to do.
Then, check what it's actually doing. As a debugging technique, I would recommend adding some print statement at the start of the function call:
System.out.println("minChange(" + a + ", " + integerList + ")");
...so that you can see a log of what happened before the crash. You can also use a debugger for this purpose.
Finally, once it works on some simple cases, write a fuzz tester that checks your algorithm on a bunch of random lists and as of different sizes, to see if there are any cases that you missed.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
i have an array of objects, i want to add objects in this array using a method named "AddProd()" .but in order to add in the right case of the array i have to know where the first empty case in the array is .
this is the Add Method :
public void AddProd(Produit p){
int notempty = 0;
int i = 0;
while(produits[i] != null){
notempty++;
i++;
}
if (notempty < 49) {
produits[notempty + 1] = p;
}
}
let me explain to you first i have a while loop that checks where the first null case is. the while loop keeps incrementing (i++) till it finds an empty case .
the problem is when i run i get two errors :
Exception in thread "main" java.lang.NullPointerException
at prosit.pkg2.v1.pkg0.Magasin.AddProd(Magasin.java:27)
at prosit.pkg2.v1.pkg0.main.main(main.java:22)
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)
this is (Magasin.java:27) : while(produits[i] == null){
i think that the comparaison to null is not correct and the second error is when i call the method in the main class .
Any solutions please and thanks .
Problem is you haven't initialized the array produits, itself is null.
I'm trying to make some instructions when there will be appropriate minimum integer value. For example: when variable "round_min" = 10 -> there are some instructions. When "round_min" = 100 -> there is another instruction.
I try to implement function which finds minimum value in HashMap.
For example: I have two elements in HashMap. And there is finding minimum value, and it's displaying in TextView properly.
But when I want to use this variable "round_min" to another function there are displaying all values in hashmap. I want to have always the minimum.
Below I present code:
int round_min;
// nearestDistances is a hashmap where I put distances
Map.Entry<String, Float> nearestMarker = null;
for (Map.Entry<String, Float> entry : nearestDistances.entrySet()) {
if (nearestMarker == null || nearestMarker.getValue() > entry.getValue()) {
nearestMarker = entry;
round_min = Math.round(nearestMarker.getValue());
Log.e(" MIN ", round_min + "");
// it displays in log.e all values
// this function see all values, not only minimum
DisplayMinimumValue(getApplicationContext(), round_min);
Log.e(" ROUND MIN ", round_min + "");
tvDistanceToNearest.setText(String.valueOf(round_min)); // there is displaying only minimum value
}
}
Could someone help me to find the problem and how to figure out with it?
move all the lines
// this function see all values, not only minimum
DisplayMinimumValue(getApplicationContext(), round_min);
Log.e(" ROUND MIN ", round_min + "");
tvDistanceToNearest.setText(String.valueOf(round_min)); // there is displaying only minimum value
at the end, after second } so that you are outside the loop
Since i can't comment yet... i'm unsure what your question is. I see that you are updating your round_min variable if you encounter a smaller value in the map. I also see that you have some methods that use that variable inside your iteration. What part of the program is not acting like you want it to?
Ok I'm sure I'm doing something wrong here.
result = []
for (aMp in arMap) {
println("0 " + result)
println("1 " + aMp)
println("2 " + delegate.findSingleMap(aMp))
result.addAll(delegate.findSingleMap(aMp))
println "3 " + result
}
return result
The println result are the following: (I have 2 element in arMap, so it print the four value 2 times)
0 []
1 [ID:XXX, Type:4]
2 [[First:21/Nov/2013, Type:4, error code:SXR07, ID:XXX, Test ID:5]]
3 [[First:21/Nov/2013, Type:4, error code:SXR07, ID:XXX, Test ID:5]]
0 [[First:21/Nov/2013, Type:4, error code:SXR07, ID:XXX, Test ID:5]]
1 [ID:YYY, Type:4]
2 [[First:12/Oct/2012, Type:4, error code:SXR07, ID:YYY, Test ID:6]]
3 [[First:12/Oct/2012, Type:4, error code:SXR07, ID:YYY, Test ID:6]]
As you can see the findSingleMap function work properly, but the second time I use the AddAll, my result array loose the value XXX.
What am I doing wrong?
As stated by the OP int the comments the method findSingleMap modifies the (global) result variable.
for (aEl in map) {
result = result.findAll { it[aEl.key] == aEl.value }
}
return result
Not writing def in front a variable declares it (in simple scripts) global, which might result in strange behaviour like this. So don't do it, unless you have to codegolf.