This code gives me a Exception in thread "main" java.lang.NullPointerException. The exception occurs at the if statement at the bottom of the code.
public boolean printEmployees(Node Head){
boolean isSuccessful = true;
Node nodeChecker = new Node();
nodeChecker = Head;
int hospitalEmployeeCount = 0;
int doctorCount = 0;
int surgeonCount = 0;
int nurseCount = 0;
int administratorCount = 0;
int receptionistCount = 0;
int janitorCount = 0;
System.out.println(nodeChecker.getData().getRole());
while(nodeChecker != null){
if(nodeChecker.getData().getRole() == "h")
hospitalEmployeeCount++;
Another section of code reads data from a file and fills up a linked list. I have checked using break points and the linked list is there. nodeChecker points to the head of the linked list and when I call the System.out.println statement it prints h. I cannot figure out why the exception keeps happening.
Later on in this method I attempt to print to screen all of the information in the linked list. I have tried commenting out this section of code to test the remaining code, but it prints out as if the linked list is empty. I can check the variables in the linked list all the way up to the end of the function and it shows the data in the correct positions and the correct variables in the list.
nodeChecker is not null but nodeChecker.getData() is null, also String comparison is done incorrectly
Your while and ifstatements towards the bottom of your code need to be fixed.
Look at your while loop, it will stay looping as long as nodeChecker != null evaluates to true. However, nothing inside your loop changes its value, so it will always evaluate to true, which can lead to some problems.
At the bottom, in your "if" statement, there are four things which could possibly be null: nodeChecker, getData(), getRole(), or "h".
Since you are in the loop, we already know that nodeChecker is not null. "h" is trivially not null. If getRole() is null, there won't be an exception, because null == "h" will just evaluate to false.
Thus, by exclusion, getData() must be evaluating to null.
There are a few ways to get around this issue. One easy way is just adding an extra term in your if statement, as follows:
Data data = nodeChecker.getData();
if (data != null && data.getRole().equals("h")
What this is doing is taking advantage of http://en.wikipedia.org/wiki/Short-circuit_evaluation. Basically, if data == null, the LHS of the if statement will evaluate to false. Since it is an "and" statement, since the LHS is false, the statement cannot equal true, so the RHS will not bother to evaluate. If data != null, the LHS would then equal true, and the RHS will be evaluated. This protects from the null exception which comes from calling the getRole() method on a null object.
Also, make sure that you are using .equals() to check string equality, since "==" checks the equality of the references, while ".equals()" checks the equality of the value.
Related
I was trying to read a program of removing duplicate elements in a linked list. I am confused about the break conditions put in the while loop. Below is the code.
public static <T> void removeDuplicates(SinglyLinkedList<T> list) {
SinglyLinkedList<T>.Node current = list.headNode; // will be used for outer loop
SinglyLinkedList<T>.Node compare = null; // will be used for inner loop
while ( current != null && current.nextNode != null) {
compare = current;
while (compare.nextNode != null) {
if (current.data.equals(compare.nextNode.data)) { //check if duplicate
compare.nextNode = compare.nextNode.nextNode;
} else {
compare = compare.nextNode;
}
}
current = current.nextNode;
}
}
The statement while ( current != null && current.nextNode != null) is confusing to me. If I remove current != null from the statement the output is produced same. Suppose the list is 1 -> 2 -> 3 -> null. Now initially current is at 1 , then if we traverse the list and when current points to 3 , at that moment (current.nextNode == null) and if I use only while( current.nextNode != null , that does the job for me. Then why the author has used current != null. Please help me clear the confusion.
A completely empty list would have current be null. The dot is the dereference operator - dereferencing null causes a NullPointerException. Hence, calling that method with an empty list would cause an NPE whereas the correct action is to do nothing ('remove all duplicates from this empty list' is a job that can be done, and it is done by doing nothing - there are no duplicates in an empty list, thus, nothing to remove).
For a non-empty list, indeed, that part of the while clause is never going to be relevant. Given that it would never get there (the last node in the list would already fail the while clause due to having a current.nextNode of null).
I am making an app in which the user types in a list of tasks, and that list is saved to an array. Each task in the array is an instance of the Assignment class. However, I realized that in java it is not possible to add an element to an array after the array is created. So, what I did was I created an array called tasks which consisted of many null values: Assignment[]tasks = {null, null, null, null, null, null, null, null, null, null, null, null};. When I want to add a task to the array, I just replace the next null value with the object. However, I also need to have an array of just the tasks, with no null values. So I created an array called full_tasks for all of the elements that aren't null:
for (Assignment task: tasks) {
if (task != null) {
realLength += 1;
}
}
Assignment[] full_tasks = new Assignment[realLength];
for (int i=0; i <= full_tasks.length - 1; i++) {
full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
}
So now, the full_tasks array should be an array of all the tasks, none of which are null, right? However, when I run the app, it can't launch the activity, an error it says is caused by a null pointer exception:
Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.example.lb.homeworkappv11.Assignment.name' on a null object reference
at com.example.lb.homeworkappv11.Schedule.sortTasks(Schedule.java:64)
The line that the error points to is:
full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
I'm still not totally sure what a null object reference is, but I think it means that one of the elements in the full_tasks array is null. Would that be correct? And if it is, what can I do to make sure that the full_tasks array is only the non-null elements in the tasks array?
Thank you so much!
Edit: the constructor function for the assignment class is:
public Assignment(String name, int days, int time) {
this.name = name;
this.days_due = days;
this.time = time;
this.toSortBy = "nothing";
}
A null reference is just that null. In your code it is tasks[i].name where you try to call name on tasks[i] so tasks[i] is null.
There is one scenario I can think of, where your code would definitely throw a NullPointerException.
So, I will assume your tasks array can look looks like this:
tasks = [task0, null, task2, task3, null, task5]
Then full_tasks will have a size of 4 but
for (int i=0; i <= full_tasks.length - 1; i++) {
full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
}
will throw a NPE as soon as i == 1 because tasks[1] is null.
So, if you want to fill full_tasks with only non-null tasks make sure you got the right indexes of tasks.
Here's what I think
You are just finding the number elements that are not null. You don't know where in the array thest null's are present.
Suppose ONLY the first element is null. So realLength will be 7. The latter for loop runs from i=0 to i=7. When i=0, tasks[i].name tries to access the name field of the first element; but your first element happens to be null`. That's where things go wrong.
Solution:
There are a number of solutions. The most efficient one I can think of uses an ArrayList.
To get around using arrays, you should store the indices of all elements that are not null. That's one way.
Here's another:
for (Assignment task: tasks) {
if (task != null) {
realLength += 1;
}
}
Assignment[] full_tasks = new Assignment[realLength];
int count = 0;
for (Assignment task: tasks) {
if (task != null) {
full_tasks[count] = new Assignment(task.name, tasks.days_due, task.time);
count++;
}
}
You can think of null as something not exists, for example when you try to get task.name, where task is null, you get error, because you try to get name from some something which does not even exists.
Actually what your code is doing now is check how many non-null items in the original array, and try to extract the extra the first n items from the array to a new array.
i.e. if the list is {null, null, non-null, non-null}, it has 2 non-null item, however your code wrongly extracts the list of the first 2 items which are {null, null}
Edit, to actually do what you want:
ArrayList<Assignment> fullTaskList = new ArrayList<Assignment>();
for (Assignment task: tasks) {
if (task != null) {
fullTaskList.add(task);
}
}
//optional
Assignment[] fullTasks = fullTaskList.toArray(new Assignment[fullTaskList.size()]);
The problem in your code is here:
(tasks[i].name, tasks[i].days_due, tasks[i].time).
Although you're counting the real size, there could be some null value in between that is causing it to be get a null object from the list tasks[i].
A good idea to solve this is by using a List instead of an Array. A List can be increased or decreased as you want, you just have to add or remove an item of your object type. For example:
List<Assignment> list = new ArrayList<>();
Assignment assignment1 = new Assignment(etc.);
list.add(assignment1);
list.get(0) //-> returns the Assignment object that you added.
Then you can use list.size() to get the size to know how many items are there, or to remove the last item. And you would have no problems to add new items to the list.
It seems you are trying to copy and compact the tasks array into the full_tasks array (removing the null elements), but you are doing this partially incorrect since you are accessing tasks[i] in the second loop without checking whether its is null.
Instead of:
for (int i=0; i <= full_tasks.length - 1; i++) {
full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
}
you could write something like this:
for (int i = 0, f = 0; i < tasks.length; i++) {
if (tasks[i] != null) {
full_tasks[f] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
f++;
}
}
But then again to solve your original problem, regarding the fact that you cannot add any elements to an array, I suggest to use an ArrayList instead of a simple array. This allows you to add items with ArrayList.add(assignment) and remove them again with ArrayList.remove(index).
Seems like "tasks" list is empty. Make sure its get populated or put a null check
like :
if(tasks[i] !=null) {
full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
}
This is a sample implementation of indexOf() in LinkedList on Oracle's website. I'm a little confused on how the if loop works here:
public int indexOf(E e) {
for (ListIterator<E> it = listIterator(); it.hasNext(); )
if (e == null ? it.next() == null : e.equals(it.next()))
return it.previousIndex();
// Element not found
return -1;
}
So the ListIterator object is created at the head of the list. for loop goes on until the iterator reaches the list's end, and the if loop checks if the target object is found. The part I did not understand though, is that why does the if loop check it.next() == null when e == null? Could someone help walk me through how it's done when input e is null?
The loop checks if it.next() == null only if e == null this is done to avoid NullPointerException when evaluating e.equals(it.next()).
if e != null, then the regular e.equals() method is invoked.
null is a valid "element" that can be inserted to a LinkedList, so this must be taken into consideration.
The position of the last element is not inserted. Note that unlike the text book data structure where the last element in a Linked List is null, in here - when you get to the last element - it.hasNext() will be evaluated to false, without letting you see this "junk" element.
If e is null, the indexOf() method will iterate until it finds another null element in the iterable object you have passed and return its index.
I think you've misunderstood what is going on with regards to the ternary operator.
This line:
if (e == null ? it.next() == null : e.equals(it.next()))
Checks to see that e is null, if it is, then it will check that the iterator's next element is null (this effectively stops the iteration operation so as to avoid a NullPointerException), otherwise: (if e is not null - i.e. it has some value in it), perform the comparison:
e.equals(it.next())
if (e == null ? it.next() == null : e.equals(it.next())) - this is a java ternary operator
it.next() == null is a null check(returning true or false to see if this is the last element)
if that is true
return it.previousIndex(); executes
if e is not null, then
e.equals(it.next())
executes and if thats true,
return it.previousIndex(); executes
which is the index of the element your want the index of. Hope my explanation isn't confusing.
I need to write a method that starts with a single linked list of integers and a special value called the splitting value. The elements of the list are in no particular order. The method divides the nodes into two linked lists: one containing all the nodes that contain an element less than the splitting value and one that contains all the other nodes. If the original linked list had any repeated integers (i.e., any two or more nodes with the same element in them), then the new linked list that has this element should have the same number of nodes that repeat this element. The method returns two head references - one for each of the linked lists that were created.
I have been spent countless hours trying to get this right and think this is the closest but I have an error while compiling that my copyTail* IntNodes may not be initialized. I also may be completely wrong with my code....
Any help pointing in me in the right direction??
public static IntNode[ ] listSplitLessGreater(IntNode source, int splitter)
{
IntNode copyHeadLess;
IntNode copyTailLess;
IntNode copyHeadGreater;
IntNode copyTailGreater;
IntNode[ ] answer = new IntNode[2];
boolean less = true;
boolean greater = true;
// Handle the special case of the empty list.
if (source == null)
return answer; // The answer has two null references .
//Split list into two lists less and greater/equal than splitter.
while (source.link != null)
{
if (splitter < source.data)
{
if (less)
{
copyHeadLess = new IntNode(source.data, null);
copyTailLess = copyHeadLess;
less=false;
}
else
{
source = source.link;
copyTailLess.addNodeAfter(source.data);
copyTailLess = copyTailLess.link;
}
}
else
{
if (greater)
{
copyHeadGreater = new IntNode(source.data, null);
copyTailGreater = copyHeadGreater;
greater=false;
}
else
{
source = source.link;
copyTailGreater.addNodeAfter(source.data);
copyTailGreater = copyTailGreater.link;
}
}
}
//Return Head References
answer[0] = copyHeadLess;
answer[1] = copyHeadGreater;
return answer;
}
I think you're making it more complicated than it needs to be, by modelling a list just with a single class (IntNode). If you model it as "the list" and "a node in the list" then it's easy to have an empty list. You also don't need to keep track of both the head and the tail - the list can do that. At that point, it's very simple:
Create two empty lists, one for "lower" and one for "not lower"
Iterate over the original list:
Work out which list to add the element to
Add the element
Return both lists (e.g. using an array as you have done)
Note that even without that, you can make your code simpler by just using null to mean "I haven't got this list yet". At the moment your code won't compile, as copyHeadLess etc aren't definitely assigned when they're used. You know that you won't try to use them until they've been assigned, but the compiler doesn't. I'd still recommend the remodelling approach though :)
If source isn't null, but source.link is null (list is only composed of one element) then you never assign to your copyHeadLess, etc, variables. Try initializing them to null or whatever the default is:
IntNode copyHeadLess = null;
IntNode copyTailLess = null;
IntNode copyHeadGreater = null;
IntNode copyTailGreater = null;
IntNode[ ] answer = new IntNode[2];
boolean less = true;
boolean greater = true;
// Handle the special case of the empty list.
if (source == null)
return answer; // The answer has two null references .
//Split list into two lists less and greater/equal than splitter.
while (source.link != null)
{
// what about case where source isn't null but source.link is null?
}
//Return Head References
answer[0] = copyHeadLess; // this may have never been assigned in your original code
answer[1] = copyHeadGreater; // this may have never been assigned in your original code
return answer;
}
Welcome!
I have a recursive public static method named less that takes a tree node (an original binary tree, not really a search tree) and a int parameter that returns if all the values in the tree are less than the integer. So, I would use a public class TN { public int value; public TN left, right; public TN(int v, TN l, TN r) {value = v; left = l; right = r;} }
So, my method would look like this:
public static boolean less(TN s, int toFind){
if (s == null)
return true;
else{
if(s.value <= toFind)
return less(s.left, toFind) && less(s.right, toFind); // right here do I return true? or do I have to somehow recall recursively
else
return false;
}
I was wondering if that was right or am I missing something??? Do I have to return true and false??
There are much more elegant, OO ways to write this. My recommendation would be to make less() a non-static member function of the TN class. That way, if the tree's root node is called root, you just call root.less(). Each call to less() will then call left.less() and right.less().
Since you posted example code that wouldn't even compile, I'm wondering if you're using an IDE, or even tried to compile your class using javac. I strongly recommend getting Eclipse, Netbeans, or another IDE if you're new to Java.
return less(s, toFind);
should be:
return less(s.left, toFind) && less(s.right, toFind);
I don't know why the function is static.
As mentioned before, your first part should just be:
if (s == null) return true;
(EDIT: This will let you get a true result when all nodes meet the condition. You have an == in there that should be a <).
EDIT: Ok, you've got a lot of problems than just those I mentioned. You need to logically step through your code.
You need to traverse your tree, so you'll need to call your function on your children nodes. Next, you need to return true as your default result. That way, when you reach a number greater than what you're looking for, you can return false immediately without traversing any of the children. I hope I've helped you enough with the logic for you to get through the rest of it yourself.
First, if (s = null) should be if (s == null) as you are doing a comparison, not setting the value of s to null.
The statement return less(null, toFind); keeps calling your method - you'll overflow your stack.
Notice how there's no way that your function could ever return true because every time you terminate the recursion, you're returning false? And the problem is in your first check. You say that "all the values in the tree are less than the integer." Well, in an empty tree, all the values (of which there are none) are indeed less than any integer, so you should return true in that case.
Also, while you say "less than", you're comparing for equality, so you're actually checking whether all the values are equal to the integer, not less than it.