I am new in Java and I have a problem in using if statement within while loop.
I wrote the code as follows:
while(lexicalizations.hasNext())
{
myObject = lexicalizations.next().getObject();
language= myObject.getTermLanguage();
if (language.equals(languageCode)) {
System.out.println(lexicalizations.next());
}
}
However, whenever the if condition is true, the program executes its block and then terminates the while loop. So, the rest of items are not checked out.
How could I solve that?
Thanks so much.
Cheers,
Aya.
Each invocation of Iterator.next() moves the iterator to the next element of the collection, therefore you must be very careful not to call this method more than once per iteration. You must save the element into a local variable and work with the variable throughout the loop body.
In order to systematically avoid this kind of pitfalls, always prefer to use the enhanced for loop whenever applicable:
for (String lex : lexicalizations) {
... your code uses lex here ...
}
Note that when you do that println you "consume" the next element, so if there is only one left there will be zero when you get back to the while.
You are moving to the next object in the iterator within if statement block. To avoid this just use myObject and you will 'visit' every object:
while (lexicalizations.hasNext())
{
myObject = lexicalizations.next().getObject();
language= myObject.getTermLanguage();
if (language.equals(languageCode)) {
System.out.println(myObject);
}
}
Related
I couldn't find any topic about this. I want to know if it is safe to change the reference for the list class during a loop like the one bellow:
Tree minimalTree = someTree;
for (Tree st : minimalTree.getSubtrees()) {
if (condition)
minimalTree = st;
}
Does the iterator gets reset and starts again for the new reference?
Edit: I forgot to say: this code is suited for situations where I want to narrow down the search for elements in the tree, let's say, the smaller tree that contains certain elements. In this case, it would be faster to keep looking only for the inner structures of "minimalTree" instead of the entire "someTree" structure.
No, the iteration won't be reset. According to the JLS:
The enhanced for statement is equivalent to a basic for statement of
the form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
{VariableModifier} TargetType Identifier = (TargetType) #i.next();
Statement
}
The definition makes it obvious that the iterator is only initialised once, before the first iteration of the loop.
The behaviour when iterating across an array with an enhanced for statement is similar in this respect.
However I'd personally consider it poor practice as it makes the code hard to understand.
Actually, there are two questions:
I want to know if it is safe to change the reference for the list class during a loop like the one bellow:
Yes, it is safe. And for safe I mean: changing the reference does not interfere with the already running loop.
Does the iterator gets reset and starts again for the new reference?
No, the iterator is never reset. It would be exactly the opposite of safe.
In my opinion, it is not a good practice to change iterator or collection variables inside a loop. It makes the code harder to understand, and probably the result is not what you expect when you do that (like in your case I understood you expected the loop to start over reevaluating the collection).
In your case, encapsulate in a method and recursively call it on subtree:
Tree findMinimalTree(Tree tree) {
for (Tree st : tree.getSubtrees()) {
if (condition)
return findMinimalTree(st);
}
return tree;
}
I am having a discussion (read argument!) with one of my colleagues. I maintain that this code is very wrong but he thinks there is nothing wrong with it:
for (Iterator<String> iter = collectionOfStrings.iterator(); iter.hasNext();) {
String item = iter.next();
...
}
I maintain that this code is wrong because there is a duplication of looping. Either use Iterator or use a For loop but there is no need to use them both at the same time.
I would re-write the code as follows:
Iterator<String> iter = collectionOfStrings.iterator();
while (iter.hasNext()) {
String item = iter.next();
...
}
What do you think?
Neither code is not "wrong", in the sense that both do what is expected. The second code, although equivalent, pollutes the local variables, because iter remains defined after the loop ends.
Both of your examples are syntactically correct. One advantage of putting the declaration in the for loop is that the variable is released after the code block ends, whereas the iterator persists after the while loop ends
The second is good.
The first is slightly better. It limits the loop variable's scope.
But since Java 1.5, the foreach loop can sometimes be more elegant than either:
for ( String item : collectionOfStrings ) {
...
}
Actually it's the same. For is just a variation of while, or while is just a variation of for, however you like to put it. You can write a for
for (init;cond;incr){
...
}
like this
init
while(cond){
....
incr
}
Your colleague is right. The first code, with the for loop, should run just fine.
In fact, while is also a loop, so both your code and his contains one loop and iterator.
I'm writing a program to implement an algorithm I found in the literature.
In this algorithm, I need a while loop;
while(solution has changed){
updateSolution();
}
to check if the while condition is satisfied, I have created an Object (of the same type as solution) called copy. This copy is a copy of the solution before the solution is updated. So if there's been a change in the solution, the condition in the while loop is satisfied.
However, I am having some problems finding the best solution for the conditions of both objects as the while loop is executed, since I start with an empty solution (resultset) and the copy is also empty at that time (both called with the constructor of the class). This means that when the while loop is executed, both objects are equal and thus all statements in the while loop are not executed.
My solution for now is to create a dummy variable that is set to true before the while loop and is set to false in it. I doubt that this is the best solution, so I'm wondering if there is a standard solution to this problem (some way to force the program to always run the first iteration of the while loop)?
Code as it is now:
SolutionSet solution = new SolutionSet();
SolutionSet copy = new SolutionSet();
boolean dummy = true;
while((!solution.equals(copy)) || dummy){
dummy = false;
copy = solution.copy();
solution.update() // here some tests are done and one object may be added to solution
}
Use do {} while (condition);.
You can do that with a do-while statement:
SolutionSet solution = new SolutionSet();
SolutionSet copy = new SolutionSet();
do {
copy = solution.copy();
solution.update() // here some tests are done and one object may be added to solution
} while (!solution.equals(copy));
While tests the condition and, if is true, runs the specified code.
There's one construction that's a bit different: Do... While. It executes some code and, at the end of the block, checks whether some condition is met. For example
do {
this;
that;
that another;
} while (this == true);
Do I always have to return something using Worker Thread in Swing? What if I don't have any return value? I just want to use the worker thread to run an infinite for loop... so what to return? and even if I write a dummy return statement after the infinite for loop, say for e.g return 0; then also it will probably say "code not reachable".
I suspect you haven't tried it. The code you've suggested in the comment should work fine:
public Object construct() {
for (;;) {
Node.execution();
Clock.incrementTimeTick();
System.out.println(Clock.getTimeInTick());
repaint();
}
// End of loop is unreachable, so no need for a return statement.
}
A tight loop like this seems like a bad idea to me, and the repaint() code will need to be made appropriately thread-safe, but it should compile...
Personally I prefer to use while (true) for "forever" loops, but for (;;) should work too.
Implement the worker as SwingWorker<Void, SomeObject> and just return null. Trick the compiler about the infinite loop. Make it depending on some method that in the runtime always return true.
A method like the follow will compile without any compilation errors:
public Object foo() {
for (;;) {
// do something ... or nothing
}
}
The reason is that any statement following the for loop is unreachable, according to the rules set out in the JLS 14.21. Specifically
Any for loop with no condition expression (or a condition expression that is a compile-time constant expression with value true) cannot "complete normally".
Any statement in a block that is preceded by a statement which cannot complete normally is unreachable.
I've run into this while writing a Traveling Salesman program. For an inner loop, I tried a
for(Point x:ArrayList<Point>) {
// modify the iterator
}
but when adding another point to that list resulted in a ConcurrentModicationException being thrown.
However, when I changed the loop to
for(int x=0; x<ArrayList<Point>.size(); x++) {
// modify the array
}
the loop ran fine without throwing an exception.
Both a for loops, so why does one throw an exception while the other does not?
As others explained, the iterator detects modifications to the underlying collection, and that is a good thing since it is likely to cause unexpected behaviour.
Imagine this iterator-free code which modifies the collection:
for (int x = 0; list.size(); x++)
{
obj = list.get(x);
if (obj.isExpired())
{
list.remove(obj);
// Oops! list.get(x) now points to some other object so if I
// increase x again before checking that object I will have
// skipped one item in the list
}
}
The first example uses an iterator, the second does not. It is the iterator that checks for concurrent modification.
the first code is using an iterator so modifying the collection is not allowed. The second code you are accessing each object with x.get(i), so not using an iterator, modifications thus are allowed
You cannot modify a List while you are iterating over it which you are doing in the first example. In the second you simply have a regular for loop.
If you run the code and observe you find that first iteration of the loop works fine but the second throws ConcurrentModicationException
if is because next() method checks if the number of the elements did not change.
For nice explanation see http://javaadami.blogspot.com/2007/09/enhanced-for-loop-and.html