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.
Related
Could someone tell me what's missing in my code. I am trying to remove the first occurrence of a given node value.
It fails very few test cases, but I am not sure what I am missing. Here is my code :
public boolean remove(E obj) {
if (obj == null)
throw new IllegalArgumentException("Violation of precondition : remove(E obj)");
DoubleListNode<E> current = head;
for (int i = 0; i < size; i ++) {
if (current.getData().equals(obj)) {
E result = remove(i);
return true;
}
current = current.getNext();
}
size --;
return false;
}
That recursive call to remove() inside the if block looks wrong.
You are already inside the list, you identified the first matching object. So now your code has to really remove that matching object. Removing would mean to update both links accordingly.
Do these things on paper! Draw a double linked list with nodes and the links between them. Then ask yourself what removing a node that has one or two links coming in (and potentially going out) actually means. You will have to change the links from the previous node and the one following the node that is to removed!
I'm trying to do a linkedlist for an assigment i have, this ask explicitly to create, from scratch a linkedlist and some derivated types like a queue and a stack, this is just some college homework, and i realize how to make a node class and a linkedlist class, but i'm struggling to create the addAll() method in this linkedlist class, this is what i have.
if i must bet, i say is the Collection c one, but then, i'm trying to add list of stuff there, in order to pass him's content to the new list, obiusly is not ready and obiusly doesn't work.
Can you tell me how i can pass some kind of "proto-list" in order to pass them data inside the new list?
(I know i must use somekind of for(objects) but i'm failing to pass some data through the parameter, which will be the right parameter to put there?)
public boolean addAll(Collection c) {
for (int i = 0; i < (this.listaNodos.size()); i++) {
//for (T someT : c){
// Node newNodo = new Node(someT);
//}
//i know the one down there is not gonna do anything, because
//i'm not accesing the data, but one problem at a time would ya ;)
Node newNodo = new Node(someT);
Node actualNodo = this;
boolean processFinished = false;
try{
if(index >= this.listaNodos.size() || index < 0){
throw new IndexOutOfBoundsException();
}
do{
if(index == actualNodo.getIndex())
{
actualNodo.setData(someT);
processFinished = true;
return true;
}
else
{
actualNodo = actualNodo.nextNode;
}
}while(!processFinished);
return false;
}catch(IndexOutOfBoundsException ex)
{
throw ex;
}
}
return false;
}
Can you tell me how to fix it to make it work?
Any request for clarification, constructive comment, or question would be greatly apreciated too.
Thanks in advance
I assume you already have an add() method of some sort right? If so, you can go over each element in c and add it using the add method:
public boolean addAll(Collection<T> c) {
boolean changed = false;
for (T t:c) {
changed |= this.add(t);
}
return changed;
}
I'm assuming the returned boolean means whether this list has changed, this is how it is defined in the Collection contract: https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#addAll(java.util.Collection).
You were also missing a generic type for your add method, so I added one. I assume your class definition looks somthing like this?
public class MyLinkedList<T>
I have an abstract class Usuarioand an ArrayList<Usuario> with objects of its three subclasses. I now want to iterate through the ArrayList and return a value depending of the result of using instanceof against that object.
I get an error: java.util.NoSuchElementException.
I suppose it is because of the iterator being an object of Iterator and not from any of the subclasses from Usuario. Am I right? is there any solution for that?
public int comprobarDni(String dniAComprobar, ArrayList<Usuario> listaUsuarios) {
Iterator<Usuario> itUsuarios = listaUsuarios.iterator();
while (itUsuarios.hasNext()) {
if (dniAComprobar.equals(itUsuarios.next().getDni())) {
if (itUsuarios.next() instanceof UsuarioBiblioteca) {
return 1;
} else if (itUsuarios.next() instanceof Bibliotecario) {
return 2;
} else if (itUsuarios.next() instanceof BibliotecaExterna) {
return 3;
}
}
}
return 0;
}
Iterator.next() returns the next item and advances the cursor. That's not what you want so try this instead:
Usuario usuario = itUsuarios.next();
...
if (usuario instanceof UsuarioBiblioteca) {
return 1;
} else if (usuario instanceof Bibliotecario) {
return 2;
} else if (usuario instanceof BibliotecaExterna) {
return 3;
}
With your code consider the following case: listaUsuarios only contains two elements of type BibliotecaExterna. Your first call to next() will return the first element but since the type doesn't match you issue the second call to next() which returns the second element. Again the type doesn't match so you issue a third call to next() (itUsuarios.next() instanceof BibliotecaExterna) but there is no third element and hence you'll get the NoSuchElementException.
You are invoking itUsuarios.next multiple times during your iteration.
Therefore you might end up invoking it while the List has already been iterated fully, which will throw java.util.NoSuchElementException.
Consider assigning a Usuario value once, and referring to that instead:
while (itUsuarios.hasNext()) {
// reference this instead of itUsuarios.nex() for next references
Usuario usuario = itUsuarios.next();
Or...
Go with fast enumeration for cleaner looking code:
for (Usuario usuario: listaUsuarios) {
...
There is a huge misconception in your code:
If your current element is an instance of BibliotecaExterna it will call next() in the first if-statement and check it against UsuarioBiblioteca. But then the element has already changed.
Instead store it at the beginning:
Usuario element = itUsuarios.next();
if(element instance of ...)
...
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 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.