could someone help explain how this indexOf() implementation works? - java

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.

Related

Remove duplicate elements from a linked list

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).

Sort ArrayList by Date in Java

I'm trying to sort a list of Product objects by their useby Dates, but some of the objects may have their Date useby = null
What I want to do is sort the list by "useby" Dates, and put all the Objects that has Date useby = null on the bottom or on the top of the list.
public static void sort() {
Collections.sort(list, new Comparator<Product>() {
public int compare(Product o1, Product o2) {
if (o1.getUseDate() == null || o2.getUseDate() == null) {
return 0;
} else {
return o1.getUseDate().compareTo(o2.getUseDate());
}
}
});
}
This is my code and I don't know how to fix this.
if (o1.getUseDate() == null || o2.getUseDate() == null). Here you are checking if either of the two Product's has a null date. If even one of them does the return result of 0 means that the Comparator will see them as equal. Even if just one of them has a null date. Here you probably want to do some more in-depth checking. The following code will result in Product's with null Dates being put at the start.
if(o1.getUseDate() == null && o2.getUseDate() == null)
return 0; //They are both null, both equal
if(o1.getUseDate() == null && o2.getUseDate() != null)
return -1; // The first is null and the second is not, return the first as lower than the second
if(o1.getUseDate() != null && o2.getUseDate() == null)
return 1; //The first is not null and the second is, return the first as higher than the second
else
return o1.getUseDate().compare(o2.getUseDate()); //Return the actual comparison
This is obviously a little verbose, but it should give you an idea as to what you should actually be looking for.
return 0; means that compared elements are equal (in other words you shouldn't swap them).
In case of nulls consider
returning 0 if both values are null (first value is same as second value - don't swap)
returning -1 if first value is null but second is not null (first element is lesser than second - don't swap)
returning 1 if second value is null and first is not null (first element is greater than second - swap them)
From compare javadoc:
Compares its two arguments for order. Returns a negative integer,
zero, or a positive integer as the first argument is less than, equal
to, or greater than the second.
But from this line of your code:
if (o1.getUseDate() == null || o2.getUseDate() == null) {
return 0;
we can see that you're practically telling the comparator to consider useDates as being equal when at least one of them is null, and this is not what you want.
Since null means "nothing", it's quite weird to compare the concept of nothing with a date, but if you want to allow null values, then you have to handle this situation properly, resulting into a more vorbose code:
if(o1.getUseDate() == null){
return o2.getUseDate() == null ? 0 : -1; //or +1 if you want null values at the bottom of your list
}
if(o2.getUseDate() == null){
return o1.getUseDate() == null ? 0 : -1; // or +1 ...
}
return o1.getUseDate().compare(o2.getUseDate()); // 2 non null dates, do a real comparison

Null pointer exception but variable contains a value

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.

Comparator in Linked Lists

I'm writing a program that is a linked list, trying to insert something in order and I've used this in my code but it keeps saying that it's a NullPointerException, and I'm not sure why.
public SortedLinkedList<T> add(T element) {
Node insert = new Node(element);
Then I check to make sure curr isn't null.
if (comparator.compare(curr.data, insert.data) <= 0
&& comparator.compare(curr.next.data, insert.data) > 0){
Then I check to make sure curr isn't null.
The code you've posted isn't checking to see if curr is null, it is doing a comparison, and probably trying to do a comparison on an Object that does not exist.
You should check to make sure that the next element (curr.next) in your linked list exists before you try to access it.
I dont't know what's the body of comparator.compare, but it there's no null check in that method, you should do something like this.
if (curr != null && curr.data!=null && comparator.compare(curr.data, insert.data) <= 0
&& comparator.compare(curr.next.data, insert.data) > 0){

using method that take variable number of parameters

I am trying to make a method that build new object of the class (PhoneBook) using different constructors according to the number of parameters ,, but it gives an error
( Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 )
public static PhoneBook createObjects(String fName,String lName,String num,String...optional)
{
n++;
if (optional[0]==null)
ArrayOfObjects[n]=new PhoneBook(fName,lName,num);
else if (optional[1]==null)
ArrayOfObjects[n]=new PhoneBook(fName,lName,num,optional[0]);
return ArrayOfObjects[n];
}
Instead of checking whether optional[0] == null, you should examine optional.length to determine if the optional parameter is present.
The same goes for optional[1].
Rather than checking optional[0] and optional[1] here, you should check to optional.length. Also, keep in mind that optional itself may well be null, so something like:
if(optional != null) {
if(optional.length > 0) {
// I now know that optional has at least one element in it, and optional[0] should be valid, though I don't know that it is non-null.
if(optional.length > 1) {
// I now know that optional[1] is valid, though I do not know it is non-null.
}
}
}
if you NEED non-null:
if(optional.length > 0 && optional[0] != null)
The second part, optional[0] != null will only be called if the first evaluates to true.

Categories