I am new to computer science, so forgive my ignorance. For the LinkedList that is in Java,
does the removeLastOccurrence method use the equals method between the object passed in or does it simply compare the memory location?
According to http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/LinkedList.java, the source for that method is:
public boolean removeLastOccurrence(Object o) {
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
Thus if the object you want to remove is null, then it looks for a null value in the list. If the object is not null, then it uses the equals method. However, keep in mind that unless equals is specifically overridden to implement value equality, it will default to identity equality (that is, by comparing memory addresses like == does for objects)
Related
I have to solve one problem, I don't know the reason why my code doesn't work.
I have to check if two lists I created are completely equals so they have the same value at the same position.
I'm allowed to use loops as well, even by I prefer the recursive mode.
Thank you so much for your help and time!
public static boolean checkEquality(Node n, Node m) {
if(n != null && m != null) {
boolean res = false;
while(n!=null) {
if(n.getElem()==m.getElem()) {
n = n.getNext();
m = m.getNext();
res = true;
}
else
{
res = false;
}
}
return res;
}
else
{
System.out.println("Lists empty!");
return true;
}
}
There are a couple of weak spots, so I give the solid solution:
public static boolean checkEquality(Node n, Node m) {
while (n != null && m != null) {
//if (!Objects.equals(n.getElem(), m.getElem())) {
if (n.getElem() != m.getElem()) {
return false;
}
n = n.getNext();
m = m.getNext();
}
return n == null && m == null;
}
Comparing can only be done while both n and m are not null. Your code only checks n.
== is not valid for instance for String. Instead of .equals one might also use Objects.equals which also tests for null.
getNext in every loop step.
two empty lists are also equal. Both lists should end at the same time.
The tst fails as soon as two compared nodes are not equal. So one should start with assuming a true result. And as soon as the comparison fails, one should no longer loop and certainly not overwrite res from false to true.
it would help if you elaborate what type of list u are comparing,
linkedlist or arrays. based on your function, it seems that you are planning to compare a linkedlist.
linkedlist documentation
arrays documentation
// sample comparison
boolean areIdentical(Node a_head, Node b_head) {
Node a = a_head, b = b_head;
while (a != null && b != null) {
if (a.data != b.data)
return false;
/* If we reach here, then a and b are not null
and their data is same, so move to next nodes
in both lists */
a = a.next;
b = b.next;
}
// If linked lists are identical, then 'a' and 'b'
// must be null at this point.
return (a == null && b == null);
}
I don't know why find() method does not work for some numbers. Here is the code.
I'm talking about finding element in Double Linked List.
public DLLNode<E> find(E o) {
if (first != null) {
DLLNode<E> tmp = first;
while (tmp.element != o && tmp.succ != null)
tmp = tmp.succ;
if (tmp.element == o) {
return tmp;
} else {
System.out.println("Element does not exist in a list");
}
} else {
System.out.println("List is empty");
}
return first;
}
Most likely, your issue is with :
if (tmp.element == o) {
return tmp;
}
which is comparing objects using reference equality, not value equality. You want to use .equals for that. You mention it works for some numbers, which I'm guessing means you have a DLLNode<Integer> in your test - you're probably just running into the fact that the JVM caches a small subset of Integer objects (I think between -127 and +128) so those appear to work when using ==.
You need to use equals instead of ==
== compares references, ex:
new Double( 2d ) == new Double( 2d ) will be false,
but new Double( 2d ).equals(new Double( 2d )) will be true.
public DLLNode<E> find(E o) {
if (first != null) {
DLLNode<E> tmp = first;
while (!tmp.element.equals(o) && tmp.succ != null)
tmp = tmp.succ;
if (tmp.element.equals(o)) {
return tmp;
} else {
System.out.println("Element does not exist in a list");
}
} else {
System.out.println("List is empty");
}
return first;
}
public class state implements Comparator<state>{
Point a;
Point b;
private int path_cost=0;
...
}
class Point {
int x;
int y;
...
}
for above i have:
PriorityQueue<state> openNode= new PriorityQueue<state>();
LinkedList<state> closed =new LinkedList<state>();
state currNode;
I need to check if the Point a of ANY openNode or closed equals currNode's Point a.
I could use contains if i had to match the entire object but here i just care about one variabale (Point a) of state class. I want the method to check all the nodes in PriorityQueue and LinkedList.
addition:
I am thinking about using Iterator on my priorityQueue and LinkedList. But i am not sure how to read the value of Point a using Iterator.
EDIT: Looked like I'd misunderstood slightly. It's simpler than I thought.
// I've assumed more conventional names
Point currPoint = currNode.getPointA();
for (State openNode : openNodes) {
if (openNode.getPointA().equals(currPoint)) {
return true;
}
}
for (State closedNode : closedNodes) {
if (closedNode.getPointA().equals(currPoint)) {
return true;
}
}
// No matching points
return false;
You could potentially use Guava's Iterables.concat() method to make this slightly simpler:
for (State node : Iterables.concat(closedNodes, openNodes)) {
if (node.getPointA().equals(currPoint)) {
return true;
}
}
return false;
If you need to know which node has an equal point A, just change it to:
for (State node : Iterables.concat(closedNodes, openNodes)) {
if (node.getPointA().equals(currPoint)) {
return node;
}
}
return null;
That will only find one such node, of course - there may be multiple matches.
You will have to either provide equals method on Point a for state class or just use simple iteration and iterate over both List for comparison. contains method does the same.
If you use any other method it will be time consuming.
Very odd method is use Comparator to check equality
class PointAComparator implements Comparator<State>
{
Point p = null;
public PointAComparator(Point a) {
p = a;
}
#Override
public int compare(State o1, State o2) {
return (p.x == o1.a.x && p.y == o1.a.y) ? 1
: (p.x == o2.a.x && p.y == o2.a.y) ? 1 : -1;
}
}
Above compare method returns 1 for equal else -1 so when you do sorting then each list will have elements at the start which are equal. and then you can check for first element.
i used method overriding on function equals for both the object and achieved my result.
class Point {
int x;
int y;
...
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof Point))return false;
Point otherPoint = (Point)other;
return (this.x==otherPoint.getX() && this.y==otherPoint.getY() )? true : false;
}
}
public class state implements Comparator<state>{
Point a;
Point b;
private int path_cost=0;
...
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof state))return false;
state otherState = (state)other;
return ((this.a).equals(otherState.a))? true : false;
}
}
public class LinkedList {
Object contents;
LinkedList next = null;
public boolean equals(Object item) {
return (this == item) || ((item instanceof LinkedList) && this.equals((LinkedList)item));
}
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
}
}
public class myUtil{
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
}
main(){
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
}
I think i have created a circular linkedlist here. So what i have done is to overwrite the equals method to ensure that circular references are handled:
For some reason the LinkedList.equals doesnt seem to return...is it because of my circular linkedlist, or am i missing some conditions?
The primary problem with this code is that your comparison will not terminate upon circular reference, and will loop forever if all contents fields are equal. It will always continue to the next comparison, and since the next item is always there (as it's a circle) this will continue forever.
myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
To solve this issue, the simplest method would be to add a boolean private 'visited' field to each List item. When you compare, set visited on each item after the comparison. If both are not visited and the same, then continue. If only one is visited, your lists are not identical. If both are visited, you've compared the reachable entirety of the list. Generally, having loops in your list are a bad idea, and there exist algorithms specifically to detect them. This can be a confusing topic. Here is a coverage of loop detection that may help you understand the issue further. Remember, if you use the visited field, you must unset all of them with another loop in your equals() to allow it to run again.
On another note, you do not initialize the contents field of your list nodes for the test. This is okay here, since they are initialized to null, but generally it is good practice to explicitly initialize all your fields.
Generally speaking, you also don't need the equals(Object item) override. Try
public boolean equals(LinkedList item){
if (this == item){
return true; // It's the same object
}
// Add some null checks here, I'm lazy
if (this.visited && item.visited && this.contents.equals(item.contents){
this.visited = false; //Unset
item.visited = false;
return true;
}
if (this.visited && !item.visited){
this.visited = false;
return false;
}
if (!this.visited && item.visited){
item.visited = false;
return false;
}
if (!this.visited && !item.visited && this.visited.contents.equals(item.contents){
this.visited = true;
item.visited = true;
boolean ret = this.next.equals(item.next);
this.visited = false;
item.visited = false;
return ret;
}
// Contents not equal
return false;
}
This backtracks and unsets with some basic recursion. I obviously haven't compiled this, but that's the gist of it, I think (I hope there aren't too many errors)
Two issues, first you do not have a circular linked list. The follow code creates 2 lists, list1.next = list2, list2.next = null. No circle created.
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
Second, if you DID have a circular linked list, the following would produce an infinite loop since there is no end condition reached this is because in a circular linked linked, next should never be null.
public boolean equals(Object item) {
return (this == item) || ((item instanceof LinkedList) &&
this.equals((LinkedList)item));
}
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
}
To do this effectively you need to provide SOME mechanism to iterate the list in a non-circular fashion even if this mechanism is private and not exposed to other users. One way to do this would be to mark a single node as the "root".
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
I would imagine that this is your issue as you suspected, when you perform the second expression of the && namely myUtil.equals(this.next, item.next); you enter the myUtil.equals method which performs this line:
return (x == y) || (x != null && x.equals(y));
Which in turn uses x's .equals() method, which will repeat the process for its item.next, and so on and so forth since you have a circularly linked list.
This will cause an infinite loop, this is because in the code:
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
The x.equals(y) will again invoke:
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
}
But if you are performing myList1.equals(myList1), you will not get an infinite loop because the (x==y) in myUtils.equals() will return true so infinite loop will not happen if you compare same objects.
However when you compare different objects, you will enter into an infinite loop.
This is not a circular list issue, this is because of the code design you've chosen.
Finally completed my equals method implementation. For this I had to use additional checking tools by myself. I can't tell it is effective, but some extraordinary states are checked.
public boolean equals(Object o)
{
if(!(o instanceof CircularlyLinkedList))
return false;
CircularlyLinkedList<E> list=(CircularlyLinkedList<E>)o;
if(this==list)
return true;
if(size()!=list.size())
return false;
//tail element of this object
Node<E> thisTail=tail;
//tail element of list passing as parameter
Node<E> listTail=list.tail;
//checking if tail elements of both lists are the same or not. If not rotate list till equatation is provided for tails
if(!thisTail.equals(listTail))
{
listTail = equate(list);
if(listTail==null)
return false;
}
//Each element checking
for(int i=0; i<size(); i++)
{
thisTail=thisTail.next;
listTail=listTail.next;
if(!thisTail.equals(listTail))
{
listTail = equate(list);
listTail=tail;
i=0;
if(listTail==null)
return false;
}
}
return true;
}
And equate method:
private Node<E> equate(CircularlyLinkedList<E> list)
{
Node<E> thisTail=tail;
Node<E> listTail;
for(int i=0; i<list.size(); i++)
{
list.rotate();
listTail=list.tail;
//If full rotation completes then returns null
if(list.getRotation()==0)
{
return null;
}
if(thisTail.equals(listTail))
{
return nodeList;
}
}
return null;
}
getRotation method returns count of rotation operation and changes between 0 and size-1. I hope that it will become useful.
I have a class Odp. I want to use TreeSet to keep a sorted collection of Odp objects. However, I've been having problems.
public class OdpStorage {
private TreeSet<Odp> collection = new TreeSet<Odp>();
public addOdp(Odp o) {
return collection.add(o);
}
public int size() {
return collection.size();
}
}
collection.add(Odp o) is supposed to do nothing if it's already in the tree, right? Somehow, this unit test fails:
OdpStorage ts = new OdpStorage();
Odp ftw = new Odp("LOL");
Odp ktr = new Odp("OMG");
ts.addOdp(ftw);
ts.addOdp(ftw); //should do nothing
ts.addOdp(ftw); //should do nothing
ts.addOdp(ftw); //should do nothing
ts.addOdp(ktr);
assertEquals(2, ts.size());
The assertion fails. It expects 2, but the return value is 5. Why? Could the odp.equals() function be messed up?
Similarly, calling collection.contains(o) fails, even when the there is an object in the set X for which o.equals(X) returns true.
The .equals() function of Odp: (generated by Eclipse)
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Odp))
return false;
Gene other = (Odp) obj;
if (sequence == null) {
if (other.sequence != null)
return false;
} else if (!sequence.equals(other.sequence))
return false;
return true;
}
compareTo:
/**
* this = g0
* if they are equal, g1 is presumed to come first
*
* #return -1 if g0 comes before g1; 1 if g0 comes after g1
*/
#Override
public int compareTo(Odp g1) {
if (sequence.length() < g1.getSeq().length()) {
return -1;
}
else if (sequence.length() > g1.getSeq().length()) {
return 1;
}
if (sequence.compareTo(g1.getSeq()) < 0) {
return -1;
}
return 1;
}
hashCode() is not overridden. Problem?
UPDATE
hashCode() is as follows:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((sequence == null) ? 0 : sequence.hashCode());
return result;
}
But that still doesn't solve the problem.
Your compareTo implementation never returns 0. It should return 0 when the object instances are equal.
It appears that your collection.add(o) is failing to find the object in the backing TreeMap. Does your Odp implement Comparable or are you setting a default Comparable on your TreeSet whose compare method you have implemented? If so, you will need to ensure that your compareTo (for the Comparable), or your Comparator compare method will return 0 if the objects passed in are equals.
EDIT (in response to your comment to the original post):
It is recommended that you override HashCode() whenever you override equals()
EDIT2 in response to your compareTo implementation:
If g0 and g1 are equal, you should return 0. This is the root of the problem.
Mate cleanup your equals, its got too many if/elses. replace it with a nice do/while with lots of condition tests. If all the tests pass then reutrn true...Yes its got "goto" statements but its very easy to read and even easier to insert new conditions as necessary without lots of nesting. Nesting if/elses is evil. Using "elses" is evil and almost always never needed.
#Override
public boolean equals(final Object object) {
boolean equals = false;
do {
if (this == object) {
equals = true;
break;
}
if (false == super.equals(object)) {
break;
}
final DocumentView view = Unsafe.cast(object);
if (false == this.document.equals(view.document)) {
break;
}
if (this.revision != view.revision) {
break;
}
if (false == this.user.equals(view.user)) {
break;
}
if (false == this.timestamp.equals(view.timestamp)) {
break;
}
equals = true;
} while (false);
return equals;
}