i need some help. I already runned my full code via JUnit but I still get errors. I think its because of my traverse code.
The purpose of the traverse code is to create a LinkedList in a in PreOrder.
for example: JUnit always says that something like that is wrong
assertArrayEquals( new Integer[]{2, 14, 26, 86, 122, 134, 182},
Arrays.copyOf(tree.traversePreOrder(), tree.getSize(), Integer[].class));
#Override
public Object[] traversePreOrder() {
BinaryTreeNode<T> x = root;
LinkedList<Object> y = new LinkedList<Object>();
if (x == null) {
return null;
} else {
y.add(x.value);
y.add(travPreOrd(x.getLeft()));
y.add(travPreOrd(x.getRight()));
}
return y.toArray();
}
public LinkedList<Object> travPreOrd(BinaryTreeNode<T> x) {
BinaryTreeNode<T> tmp = x;
LinkedList<Object> space = new LinkedList<Object>();
if (x == null) {
return null;
} else {
space.add(tmp.getValue());
space.add(travPreOrd(x.getLeft()));
space.add(travPreOrd(x.getRight()));
}
return space;
}
You have a big problem since you always add the results of travPreOrd, which is another List<Object> or null if the node doesn't exist.
The best solution for these cases is to maintain the overridden method as non-recursive and overload this method that uses recursion and has an argument where receives the container where it has to add the data:
public List<Object> travPreOrd(BinaryTreeNode<T> x) {
BinaryTreeNode<T> tmp = x;
List<T> space = new LinkedList<T>();
travPreOrd(x, space);
return space;
}
private void travPreOrd(BinaryTreeNode<T> x, List<T> space) {
if (x == null) {
return;
}
space.add(tmp.getValue());
travPreOrd(x.getLeft(), space);
travPreOrd(x.getRight(), space);
}
To add the contents of one list to another you use addAll.
So instead of:
y.add(x.value);
y.add(travPreOrd(x.getLeft()));
y.add(travPreOrd(x.getRight()));
you want
y.add(x.value);
y.addAll(travPreOrd(x.getLeft()));
y.addAll(travPreOrd(x.getRight()));
And then you're returning null from travPreOrd, which just makes your life harder - you then have to check for it and deal with it specially. Instead you can just return an empty list.
So instead of
if (x == null) {
return null;
}
you could do
if (x == null) {
return Collections.emptyList();
}
EDIT: Part of your problem is that you are using a List<Object> - which allows you to add anything to it, including other lists. If you instead used List<Integer>, or you used generics and had a List<T>, then the compiler would be able to tell you when you were doing the wrong thing.
Related
Below is a code snippet out of an AVL-tree implementation. It worked fine back in the days, but now it doesn't work any longer. The cause seems to be casting Object to Integer.
So the Avl structure handles Object as data, and the user (in this case main() ) does the casting. What I wanted to achieve was a generic AVL-tree with comparable objects. Actually I insert Objects alongside with a key to be able to distinguish what to sort for. They are internally put in a local class called KeyData.
Here is the code:
// private stuff above - not interesting for problem
// Public AVL tree methods
public void insert(Object thedata, String thekey) {
internal_insert(new KeyData(thedata, thekey));
}
public Object find(String key) {
Object ret = null;
KeyData x = new KeyData(null, key);
if(data != null) {
if(x.compareTo(data) == 0)
ret = data;
else if(x.compareTo(data) < 0) {
if(left != null)
ret = left.find(key);
} else {
if(right != null)
ret = right.find(key);
}
}
return ret;
}
public Object[] inorder() {
Vector<Object> v = new Vector<Object>();
iinorder(v);
return v.toArray();
}
public static void main(String[] args) {
Avl test = new Avl();
test.insert(Integer.valueOf(1090), "1");
test.insert(Integer.valueOf(343452), "2");
test.insert(Integer.valueOf(3345), "3");
//Object t2 = test.find("2");
Object lookfor = test.find("2");
Integer t2 = (Integer) lookfor; // Line 164
System.out.println("Got: " + t2.toString());
}
The outcome is like follows:
$ java Avl
Exception in thread "main" java.lang.ClassCastException:
class Avl$KeyData cannot be cast to class java.lang.Integer (Avl$KeyData is in unnamed module of loader 'app'; java.lang.Integer is in module java.base of loader 'bootstrap')
at Avl.main(Avl.java:164)
...so what's the story?
...so what's the story?
The short version is that your find method doesn't return an Integer value. So you can't cast it to an Integer.
It worked fine back in the days, but now it doesn't work any longer.
Well, you must have changed something significant in your code between then and now. (Hint: the Java language or its implementations have not changed in ways that would cause this!)
So lets take a look at your find method.
public Object find(String key) {
Object ret = null;
KeyData x = new KeyData(null, key);
if (data != null) {
if (x.compareTo(data) == 0)
ret = data;
else if (x.compareTo(data) < 0) {
if (left != null)
ret = left.find(key);
} else {
if (right != null)
ret = right.find(key);
}
}
return ret;
}
First observation is that the original indentation of your method was a mess. Bad indentation makes you code hard for everyone to read ... and understand. I have fixed it.
So the find method is recursively searches a tree, and when it finds a match. It returns whatever data is. I can't see the declaration of the Data field, but the evidence is that it is an instance of Avl.KeyData. (Which makes sense ... because you compare data with x which is a KeyData instance.)
Anyhow, that explains why the result isn't an Integer.
You haven't shown us the KeyData class, but my guess is that it has a value field that is / should be an Integer. That's what you should return. The contents of the found KeyData object's value field.
But the big problem here is your use of Object. As #NomadMaker commented, this should really be a generic type with a type parameter that will be the type of the values in the tree. Then you don't have to use a type cast in main ... and the compiler would have told you that it was incorrect for find to return a KeyData<V> instead of a V.
(There are a few other problems with your implementation ... but this is not a "clinic".)
i am writing code for lop detection in linked list using hashmap. why it goes in infinite loop?
boolean hasCycle(Node head) {
HashMap<Integer,Node> map = new HashMap<Integer,Node>();
//<Address,data>
if(head == null || head.next == null)
return false;
Node p = head;
while(p.next!=null)
{
if(map.containsValue(p.next))
{
return true;
}
else
{
map.put(p.data,p.next);
}
p = p.next;
}
return false;
}
Use the Node as key and the data field as value and then check whether the HashMap contains the key:
boolean hasCycle(Node head) {
HashMap<Node,Integer> map = new HashMap<Node,Integer>();
if(head == null || head.next == null)
return false;
Node p = head;
while(p.next!=null) {
if (map.containsKey(p.next)) {
return true;
} else {
map.put(p.next,p.data);
}
p = p.next;
}
return false;
}
And also follow the Java Code Conventions.
Your code calls
map.containsValue(p.next)
This method iterates through the whole map looking for an object that is equal to the passed argument. To do that, it calls your Node.equals() method. It is highly probable that this is where it's going into an infinite loop.
To solve it, you could just use a HashSet of the Node objects (as mentioned in the comments) and check that your equals() and hashCode() methods are correct. But there is also another way to check for cycles, which doesn't involve the use of any extra memory. You just use two iterators, one going at half the speed of the other. If there is a cycle, the faster iterator will lap the slower one.
Have you defined .equals() and .hashCode() on your Node class? if not, it defaults to ==, and if the HashMap makes a copy of your Node as it inserts or moves it in memory, and then your equivalence would fail, because == compares memory addresses.
assuming your node class is akin to
public class Node{
public int data;
public Node next;
}
you could define them as
#Override
public int hashCode(){
int nextData=next.data;
return data^nextData;
}
#Override
public boolean equals(Object other){
boolean equal=false;
if(other!=null&&other instanceof Node){
Node otherNode=(Node)other;
if(otherNode.data==data){
if(otherNode.next==null&&next==null){
equal=true;
}else if(otherNode.next!=null&&next!=null){
if(otherNode.next.data==next.data){
equal=true;
}
}
}
}
return equal;
}
For my data structures class, we have to create our own Stack data type and the implementation for it as a project. The problem I'm running into is when the professor asked us to implement an equals(Object object) method. Heres what I have so far...
package stack;
import list.*;
public class Stack <E>
implements StackADT<E>//the interface
{
List <E> values;
public Stack()
{
values = new ArrayList<E>();
}
public E push(E value)
{
values.add(value);
return value;
}
public E pop()
{
return values.remove(values.size()-1);
}
public E peek()
{
return values.get(values.size()-1);
}
/** #return true only if this Stack is empty */
public boolean isEmpty()
{
return (values.size()==0);
}
/** Clear this stack, to make it an empty stack */
public void clear()
{
for (int i = 0; i < values.size()-1; i++)
{
pop();
}
}
public String toString()
{
String result = "[";
for (int i = 0; i<values.size(); i++)
{
if (i == values.size()-1)
{
result = result + values.get(i);
}
else
{
result = result + values.get(i) +",";
}
}
result = result + "]";
return result;
}
public boolean equals (Object object)
{
if (!(object instanceof StackADT))
{
return false;
}
StackADT <E> otherStack = new Stack<E>();
for(Object o: object)//heres where i run into trouble
{
otherStack.push(o);
}
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
}
Our Stack is pretty much an ArrayList which we also built in our class. the problem is, I cant add the Object object into a stack because its not something thats iteratable(?able to be iterated over). Is there a better way to do this? I would think a get() would work, since the Stack I create is an ArrayList, but whenever I use get() on otherStack, it can't find the method. I had a temporary solution when I tried casting object as a stack(I hope im using the right terminology). It looked something like this
Stack otherStack = (Stack) object;
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
this seemed to work, but when pop() was called on otherStack, the values in the original list(the one that becomes otherStack) that was passed into the equals() method we're also popped from the original list, leading to an incorrect result. Is there a better way to do this without adding in any other methods? I'm trying to stick as close to the formula set up by my professor as possible, so I dont want to add any extra fields or methods.
any and all help is appreciated
An equals method is not supposed to create anything, not even a temporary object. Rather than creating a new otherStack, cast the object that you have checked to be StackADT, like this:
// This should be the first line of any equals() implementation:
if (object == this) {
return true;
}
// You've got this part right: you need to check the other object's type
if (!(object instanceof StackADT)) {
return false;
}
// Now that you know the type, cast the other object to StackADT<E>
StackADT<E> otherStack = (StackADT<E>)object;
// The next step is to check the sizes:
if (values.size() != otherStack.values.size()) {
return false;
}
// Finally, go through the individual elements in a loop
In the loop that follows, do not pop the other stack. Do not do anything that can modify it. Simply go through the underlying storage (i.e. values), and check elements one by one.
Don't forget to override hashCode as well: you need to do it every time when you override equals for the object to fulfill the contract specified by java.lang.Object.
I've got an object of type DocObject that contains an arraylist of DocObjects within it called children, each of which may or not contain children themselves. I'm writing a function for this object called replace() that takes a child to be searched for, and if the DocObject contains that child then the child should be replaced with newObj. I have looked around the site and searched google but nothing I've seen is working. The code below shows what I've tried:
public void replace(DocObject oldObj, DocObject newObj) {
for (DocObject child : children ) {
if (child == oldObj) {
child = newObj;
}
}
}
And this (this causes an overflow exception):
public void replace(DocObject oldObj, DocObject newObj) {
if (children.indexOf(oldObj) != -1)
children.set(children.indexOf(oldObj), newObj);
for (DocObject child : children)
child.replace(oldObj, newObj);
}
This isn't replacing the child, however, and I have checked to see that the if statement is working correctly and its condition met. How can I replace oldObj with newObj?
I would not recommend looping using the for (X x: thingWithXs) construct while manipulating the list. I would recommend using indexOf to search for the desired object and if it cannot be found, recursively calling replace on the children of the object you are looking at.
Note that you'll have to modify your replace method to accept the list of objects as an argument:
public boolean replace(List<E> list, E oldE, E newE) {
if (list == null) {
return false;
}
int index = list.indexOf(oldE);
if (index > 0) {
list.set(index, newE);
return true;
}
for (int i = 0, l = list.size(); i < l; i++) {
List<E> children = list.get(i).children;
if (replace(children, oldE, newE)) {
return true;
}
}
return false;
}
Disclaimer: The above code has not been tested. It should give you an idea as to how it can be done. Essentially what it comes down to is checking if the element you are looking for is in the list, and if not, iterating over the list and checking each set of children.
Why Methode LinkedList.contains() runs quickly than such implementation:
for (String s : list)
if (s.equals(element))
return true;
return false;
I don't see great difference between this to implementations(i consider that search objects aren't nulls), same iterator and equals operation
Let's have a look at the source code (OpenJDK version) of java.util.LinkedList
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int indexOf(Object o) {
int index = 0;
if (o==null) {
/* snipped */
} else {
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}
As you can see, this is a linear search, just like the for-each solution, so it's NOT asymptotically faster. It'd be interesting to see how your numbers grow with longer lists, but it's likely to be a constant factor slower.
The reason for that would be that this indexOf works on the internal structure, using direct field access to iterate, as opposed to the for-each which uses an Iterator<E>, whose methods must also additionally check for things like ConcurrentModificationException etc.
Going back to the source, you will find that the E next() method returned by the Iterator<E> of a LinkedList is the following:
private class ListItr implements ListIterator<E> {
//...
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
This is considerably "busier" than the e = e.next; in LinkedList.contains! The iterator() of a LinkedList is actually a ListIterator, which has richer features. They aren't needed in your for-each loop, but unfortunately you have to pay for them anyway. Not to mention all those defensive checks for ConcurrentModificationException must be performed, even if there isn't going to be any modification to the list while you're iterating it.
Conclusion
So yes, iterating a LinkedList as a client using a for-each (or more straightforwardly, using its iterator()/listIterator()) is more expensive than what the LinkedList itself can do internally. This is to be expected, which is why contains is provided in the first place.
Working internally gives LinkedList tremendous advantage because:
It can cut corners in defensive checks since it knows that it's not violating any invariants
It can take shortcuts and work with its internal representations
So what can you learn from this? Familiarize yourself with the API! See what functionalities are already provided; they're likely to be faster than if you've had to duplicate them as a client.
I decided to test this and came out with some interesting result
import java.util.LinkedList;
public class Contains {
private LinkedList<String> items = new LinkedList<String>();
public Contains(){
this.addToList();
}
private void addToList(){
for(int i=0; i<2000; i++){
this.items.add("ItemNumber" + i);
}
}
public boolean forEachLoop(String searchFor){
for(String item : items){
if(item.equals(searchFor))
return true;
}
return false;
}
public boolean containsMethod(String searchFor){
if(items.contains(searchFor))
return true;
return false;
}
}
and a JUnit testcase:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class ContainsTest {
#Test
public void testForEachLoop(){
Contains c = new Contains();
boolean result = c.forEachLoop("ItemNumber1758");
assertEquals("Bug!!", true, result);
}
#Test
public void testContainsMethod(){
Contains c = new Contains();
boolean result = c.containsMethod("ItemNumber1758");
assertEquals("Bug!!", true, result);
}
}
This funny thing is when I run the JUnit test the results are :
- testForEachLoop() - 0.014s
- testContainsMethod() - 0.025s
Is this true or I am doing something wrong ?