Recursion logic from Iterating over iterator and so on - java

Can anybody help me with recursion logic? I have a iterator object, on which I am iterating using while loop. Then in each iterated object I again have to iterate and so on.
private void handleRecursiveMethod(someMethod) {
Iterator<Sometype> methods=doingSomething(someMethod));
while(methods.hasNext()){
printingDetailsAboutThisMethod(methods.next())
// Again with each method I have to do same
// operation until methods.hasNext becomes false.
handleRecursiveMethod(methods.next());
// By calling this, it does not complete while
// loop first time.
}
}

Your function goes into while loop till the iterator has no more entries to iterate on. So I think when you call handleRecursiveMethod(methods.next()); at the end of the method, it should be throwing you a NoSuchElementException.
From your example, it seems to be that you are trying to do a depth first traversal. So, your code should look something like
private void handleRecursiveMethod(Sometype someMethod) {
Iterator<Sometype> methods=doingSomething(someMethod));
while(methods.hasNext()){
Sometype method = methods.next()
printingDetailsAboutThisMethod(method)
handleRecursiveMethod(method);
}
}

Related

Infinite loop using a iterator over a treeset and I'm invoking the next() method

import java.util.*;
import java.io.*;
public class Assignment5 {
public static void main(String[] args) throws FileNotFoundException
{
File sets=new File("test.txt"); //create file to read
HashMap<String, TreeSet<String>> hm=new HashMap<String, TreeSet<String>>(); //create hashmap
TreeSet<String> allNodes=new TreeSet<String>(); //create a treeset to hold
//all nodes. No duplicates
Scanner in=new Scanner(sets);
while(in.hasNext()) //while file has content
{ //keep scanning it
String node=in.next(); //first value in each line
String edge=in.next(); //refers to node. Second
//value refers to an edge
//of the node
allNodes.add(node); //keep track of all nodes
allNodes.add(edge); //we come across
if(!hm.containsKey(node)) //if the node is not already
{
TreeSet<String> newTemp=new TreeSet<String>();
newTemp.add(edge); //in the hash map then we
hm.put(node, newTemp); //need to add a key and
} //map its first value
else //if the node is already in
{ //the hashmap then we need
TreeSet<String> temp=(TreeSet<String>)hm.get(node); //just add the new edge to
temp.add(edge); //it
hm.put(node, temp);
}
}
System.out.println(allNodes.size());
//we now have a hash map containg any nodes that have an edge with
//a treeset showing all edges from the node
int count=0; //we go through the treemap
//and test if all nodes
Iterator iter=allNodes.iterator(); //have an edge. If a node
while(iter.hasNext()); //in the file does not have
{
System.out.println("here?");
String theKey=(String)iter.next(); //an edge then it is a leaf
if(hm.containsKey(theKey))
{
count++;
}
}
System.out.println("we made it here too");
}
}
It won't even print the "here?" message. I think it's an infinite loop but if it's not even executing the first instruction in the loop then how is it even getting stuck in the loop? What am I doing wrong? Any help would be greatly appreciated. It does print the expected size of the treeSet though.
EDIT:
A sample file for test.txt:
A B
B C
C D
The reason this doesn't work is because of the semicolon (;) after the while loop:
while(iter.hasNext());
{
//The rest of the code
}
This boils down to:
while(iter.hasNext()) {
//no instructions
}
{
//the rest of the code
}
The second part (rest of the code) is not even part of the loop, it is executed after the loop. By removing the semicolon, it will bind the sequence between the accolades ({ }) to the while instruction.
As a result you don't call the .next() method at all in the loop, and thus keep polling whether there is a next element, but since you don't advance in the iterator, there will always be a next element.
You better never use a semicolon after a while loop, not even for a single instruction like:
while(condition)
instruction;
Yes, this is valid Java. But based on experience, these things tend to eventually become hard to read. One better always uses accolades, to make it explicit that you execute only one, more or no instructions.

Remove element from ArrayList internally

I have the following code:
class Action {
public void step(Game game) {
//if some condition met,
// then remove self from action stack
game.actionStack.remove(this);
}
class Game (
public ArrayList<Action> actionStack;
public Game() {
actionStack = new Arraylist<Action>();
actionStack.add(new Action());
while (true) {
for (Action action : this.actionStack) {
action.step(this);
}
}
}
}
An exception gets thrown when game.actionStack.remove(this); occurs. Is there a way to remove the element safely from inside the Action class like I want?
I'm guessing you're getting a ConcurrentModificationException because you're calling the list remove method while iterating it. You can't do that.
An easy fix is to work on a copy of the array when iterating:
for (Action action : new ArrayList<>(this.actionStack)) {
action.step(this);
}
A slightly more efficient fix is to use an explicit Iterator and call its remove method. Perhaps have step() return a boolean indicating whether it wants to remain in the list for the next step or not:
for (Iterator<Action> it = this.actionStack.iterator(); it.hasNext();) {
Action action = it.next();
if (!action.step(this)) {
it.remove();
}
}
From : the java tutorial we get the following:
Iterators
...
Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.
Use Iterator instead of the for-each construct when you need to:
Remove the current element. The for-each construct hides the iterator, so you cannot call remove. Therefore, the for-each construct is not usable for filtering.
Iterate over multiple collections in parallel.
The following method shows you how to use an Iterator to filter an arbitrary Collection — that is, traverse the collection removing specific elements.
static void filter(Collection<?> c) {
for (Iterator<?> it = c.iterator(); it.hasNext(); )
if (!cond(it.next()))
it.remove();
}
This simple piece of code is polymorphic, which means that it works for any Collection regardless of implementation. This example demonstrates how easy it is to write a polymorphic algorithm using the Java Collections Framework.
Note: I assume, you implemented equals and hashCode methods for your class
You need to use iterator to remove like below;
class Game (
public ArrayList<Action> actionStack;
public Game() {
actionStack = new Arraylist<Action>();
actionStack.add(new Action());
while (true) {
for (Iterator<Action> it = this.actionStack.iterator(); it.hasNext(); ) {
it.remove();
}
}
}
}
Edit: step function is doing simple remove job. I move it to Game constructor
I suspect that you are getting a Concurrent Modification Exception. I would suggest you do it like this
class Action {
public void step(Game game) {
//if some condition met,
// then remove self from action stack
List<Action> tmpActionList = new List<Action>();
tmpActionList = game.actionStack
tmpActionList.remove(this);
game.actionStack = tmpActionList;
}
}
Let me know if it works.

ArrayList remove error

I'm working on a project for school but i'm a little stuck right now
My problem is that i have an arrayList of Squares
Each Square has a value(from 0 to 100). Its starting value is 9999 so i can check if its is checked.
If a square is checked i want it to be removed from the arrayList.
So after a while there will be no Squares left.
there is a little bit of code where the first value is set so thats why i check if the value is 9999.
But i get an error. One that i havent seen before.
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
Vak = Square
this is my code:
while (!vakken.isEmpty()) { // check if empty
Iterator itrVak = vakken.iterator();
while (itrVak.hasNext()) {
Vak vak = (Vak) itrVak.next(); // here is get the error
if (vak.getValue() != 9999) {// check if square value is 9999
Collection checkVakken = vak.getNeighbour().values();
Iterator itre = checkVakken.iterator();
while (itre.hasNext()) {
Vak nextVak = (Vak) itre.next();
if (nextVak != null) {
if (nextVak.getValue() == 9999) {
nextVak.setValue(vak.getValue() + 1); // set value by its neighbour
vakken.remove(vak);
checkvakken.add(vak);
}
}
}
} else {
vakken.remove(vak);
checkvakken.add(vak);
}
}
}
You are removing elements from the collection while you are iterating it. As the iterator may produce unpredictable results in this situation, it fails fast throwing the exception you encountered.
You may only alter a collection through the iterator's methods while traversing it. There should be remove method on the iterator itself, that removes the current element and keeps the iterator intact.
While iterating, you should use Iterator instance for removing object:
itre.remove();
You can try like this:
itre.remove();
ITERATOR never lets you modify when you are iterating.. you need to use loops instead.. this happens coz you are using the Iterator, same time other thread is modifying the list...

poset iteration implementation correctness

I wrote a custom iterator class that iterates over the set of numbers found in a PoSet, and here is my code:
private class IntGenerator implements Iterator {
private Iterator<Integer> i;
private Set<Integer> returnedNumbers;
public IntGenerator () {
returnedNumbers = new HashSet<Integer> ();
i = S.iterator();
}
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInSecondElmPair(p, n)) {
if (returnedNumbers.contains(p.getFirstElm())) {
returnedNumbers.add(n);
return n;
}else{
returnedNumbers.add(p.getFirstElm());
return p.getFirstElm();
}
}else if (isInFirstElmPair(p, n)){
returnedNumbers.add(n);
return n;
}
}
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
The thing is that when returning a number, I should abide by the partial order rules, that is:
1. if (x, y) belongs to R, then x should be returned before y
However the code above seems to follow that ordering but it is creating duplicates, how can I fix my code to not allow it?
NOTE: In my code, S is the set of numbers in the PoSet, it is a HashSet and R is an arraylist of pairs (pair: a class i created that takes 2 ints as param) to hold the relations in the PoSet.
Is there any way to fix this problem?
Thanks
Your next method always calls i.next(), and returns one of two things:
the value that i.next() returned
some value that is less than that value.
This means that if your poset contains {1,2,3,4} and uses the natural ordering for integers, and i.next() returns 4, then either you return 4 now (due to 1, 2, and 3 already having been returned), or you will never return 4 (because it's not less than any future value).
The reason you're getting duplicates is that you return one value for every value of i.next(), and there are some values that never get returned (see previous paragraph), so naturally there are some values that get returned multiple times in compensation. Note that you never check whether the value returned from i.next() has previously been returned by your next() method, so if an element in the poset is not greater than any other element, then when i.next() returns that element, your next() method will automatically return it, even if it has previously returned it.
I think the only sensible fix for this to completely change your approach; I don't think your current approach can readily be made to work. I think your iterator's constructor needs to copy all the elements of the poset into an acceptably-ordered list, and then the next() method will simply return the next element of that list. Or, alternatively, since your current approach already requires iterating over R on every call to next() anyway, it might make more sense to base your iterator on an iterator over R. (I'm assuming here that R is already ordered using itself; if it's not, then your for loop makes no sense at all, and will essentially return randomly selected elements.)
If you do want to try to stick with your approach, then you'll need to keep track not only of the elements that your next() method has returned, but also of the elements that i.next() returned but that your next() method did not return; you'll need to be able to return these elements later.
Also, your for (Pair p : R) loop doesn't do what you want — it automatically returns n as soon as it finds any element that is less than n that's already been returned, even if there are other elements less than n that haven't been returned yet. (This is if R is already ordered using itself. If it isn't, then this loop has even bigger problems.)

Need help stepping through a java iterator

Say I have already created an iterator called "iter" and an arraylist called "database". I want to be able to look through the arraylist and see if any element in the arraylist is equal to a String called "test". If it is, then I would like to add the element to another list.
while(iter.hasNext()) {
if(database.next() == test) {
database.next().add(another_list);
}
}
What am I doing wrong? I'm completely new to iterators in java. Do I need to write my own iterator class? Any code examples would be greatly appreciated. Thanks
The problem with your code is that every time you call .next(), it advances the iterator forward to the next position. This means that this code
if(database.next() == test) {
database.next().add(another_list);
}
Won't work as intended, because the first call to database.next() will not give back the same value as the second call to database.next(). To fix this, you'll want to make a temporary variable to hold on to the new value, as seen here:
while(iter.hasNext()) {
/* type */ curr = iter.next();
if(curr == test) {
curr.add(another_list);
}
}
(Filling in the real type of what's being iterated over in place of /* type */)
In many cases, though, you don't need to use iterators explicitly. Most of the Collections types implement the Iterable interface, in which case you can just write
/* container */ c;
for(/* type */ curr: c) {
if(curr == test) {
curr.add(another_list);
}
}
Hope this helps!
if(database.contains("test"))
{
another_list.add("test");
}
you can use the built in method contains(...)
you should use equals(...) for data comparisions
look at the javadoc to see if there is already a method present for your purpose

Categories

Resources