Regular for-loop
for (int i = 0; i < 10; i++) {
// ...
if (iWantToRepeat) {
i--;
continue;
}
// ...
}
Enhanced for-loop
for (Foo f : Bar) {
// ...
if (iWantToRepeat) {
// What can I put here?
}
// ...
}
Is there any way to repeat an iteration of an enhanced for-loop? I get the feeling there might be because it's based on iterators and if I had access to them I could do it I think.
No, you can't. In every iteration the Iterator procedes by 1 step. However you can use a do-while loop to get the same effect:
for (Foo f : Bar) {
boolean iWantToRepeat;
do {
// ...
iWantToRepeat = //...;
// ...
} while(iWantToRepeat);
}
No, you cannot repeat an element going back in the loop. The only solution is adding a new loop inside the enhanced for. In my opinion this should be the way to do that even in a classic for, going forth and back is not very clean and can be harder to understand when reviewing the code.
for (Foo f: bar) {
boolean notEnough=false;
do {
... //this code will be always executed once, at least
// change notEnough to true if you want to repeat
} while (notEnough);
}
or
for (Foo f: bar) {
boolean notEnough=chooseIfYouWantToRunIt();
while(notEnough) {
... //this code can be not executed for a given element
}
}
You should view the enhanced for loop as purely a shortcut for the 95% of times you just need to iterate through something, without doing anything "unusual" that it doesn't support (modifying what you're iterating through, iterating through some elements more than once, etc.)
However, if your use case falls into one of the above categories, you'll just have to fall back to using the standard for loop (it's hardly that much more code to write, after all, and is certainly much better than hacking around a for each loop to get the same result.)
Related
Here is the code in question, I can either check for the condition once outside:
if (booleanCondition) {
for (Integer x : integerList) {
doSomething(x);
doSomethingElse(x);
}
} else {
for (Integer x : integerList) {
doSomething(x);
}
}
Or inside:
for (Integer x : integerList) {
doSomething(x);
if (booleanCondition) {
doSomethingElse(x);
}
}
The first code sample is (imo) less readable and longer. The second one is concise and easy to understand, yet inefficiently checks repeatedly for the condition.
I'm not sure if the compiler is smart enough to be able to reduce the second example to the first (I'm using java 8, javac 1.8.0_45), what do you think would be the correct way to write this then?
If the boolean condition does not depend of the elements inside the list, then the check statement should be outside the loop.
As you're using Java 8 you can write something like :
Consumer<Integer> consumer;
if (booleanCondition) consumer = (x) -> doSomething(x);
else consumer = (x) -> { doSomething(x); doSomethingElse(x) };
integerList.stream().forEach(consumer);
It's both concise and does not repeat logic.
I am using a Do While loop but i have to test whether that condition is met half way through the loop so that if it is met it will skip that part. Is there an efficient way of doing this?
e.g. I currently have something like this:
do {
method1;
if (!condition)
method2;
} while (!condition);
EDIT: I apologise, i don't think i made it clear in the first place. The condition starts as being false, and at some point during the loop one of the methods will set the (global) "condition" to true at which point i want the loop to immediately end. I just think it's messy having to test the ending condition of the loop within it and was wondering if there was anything obvious i was missing.
Please provide more info about methods. If you can return condition from method1/2, then try:
do {
method1;
} while (!condition && !method2)
or if you pass by reference and method return always true:
while (method1 && !condition && method2 && !condition);
or:
while (!method1 && !method2);
EDIT: if:
public boolean method1/2 { ... logic ... ; condition = true; return condition;}
it's hardly depend on what you will do.
I assume that your are looking for is avoiding this additional test for efficiency because "condition" is not met most of the time (1 out of many)...
This optimization may be done by going deeper into what is really done in method1 and method2 (or on the data they are handling) and add a first "fake step" outside of the loop that will disable treatment of method2 only the first time. Would look like this:
prepare_for_loop_entering
do {
method2
method1;
} while (!condition);
if condition is the same on all the places you refer to it than
do {
method1;
method2;
} while (!condition);
as in your while loop condition will always be false (!condition will be true) unless you set it to true in method1; than you can just break; as soon as you set it to true in method1;
How about this:
method1;
while (!condition) {
method2;
method1;
}
what about this:
while (!condition) {
method1;
if(!condition)
method2;
}
How about the code below:
if(condition)
break;
Use the most generic form of a loop:
while (true)
{
method1;
if (!condition) break;
method2;
}
Further explanation
A while loop with a condition "condition" is exactly like:
while (true)
{
if (condition) break;
method1;
method2;
}
And a do-while is exactly like:
while (true)
{
method1;
method2;
if (condition) break;
}
We want neither of those, hence the code above.
I'm trying to understand the difference in behaviour of an ArrayList and a Vector. Does the following snippet in any way illustrate the difference in synchronization ? The output for the ArrayList (f1) is unpredictable while the output for the Vector (f2) is predictable. I think it may just be luck that f2 has predictable output because modifying f2 slightly to get the thread to sleep for even a ms (f3) causes an empty vector ! What's causing that ?
public class D implements Runnable {
ArrayList<Integer> al;
Vector<Integer> vl;
public D(ArrayList al_, Vector vl_) {
al = al_;
vl = vl_;
}
public void run() {
if (al.size() < 20)
f1();
else
f2();
} // 1
public void f1() {
if (al.size() == 0)
al.add(0);
else
al.add(al.get(al.size() - 1) + 1);
}
public void f2() {
if (vl.size() == 0)
vl.add(0);
else
vl.add(vl.get(vl.size() - 1) + 1);
}
public void f3() {
if (vl.size() == 0) {
try {
Thread.sleep(1);
vl.add(0);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
} else {
vl.add(vl.get(vl.size() - 1) + 1);
}
}
public static void main(String... args) {
Vector<Integer> vl = new Vector<Integer>(20);
ArrayList<Integer> al = new ArrayList<Integer>(20);
for (int i = 1; i < 40; i++) {
new Thread(new D(al, vl), Integer.toString(i)).start();
}
}
}
To answer the question: Yes vector is synchronized, this means that concurrent actions on the data structure itself won't lead to unexpected behavior (e.g. NullPointerExceptions or something). Hence calls like size() are perfectly safe with a Vector in concurrent situations, but not with an ArrayList (note if there are only read accesses ArrayLists are safe too, we get into problems as soon as at least one thread writes to the datastructure, e.g. add/remove)
The problem is, that this low level synchronization is basically completely useless and your code already demonstrates this.
if (al.size() == 0)
al.add(0);
else
al.add(al.get(al.size() - 1) + 1);
What you want here is to add a number to your datastructure depending on the current size (ie if N threads execute this, in the end we'd want the list to contain the numbers [0..N)). Sadly that does not work:
Assume that 2 threads execute this code sample concurrently on an empty list/vector. The following timeline is quite possible:
T1: size() # go to true branch of if
T2: size() # alas we again take the true branch.
T1: add(0)
T2: add(0) # ouch
Both execute size() and get back the value 0. They then go into the true branch of the and both add 0 to the datastructure. That's not what you want.
Hence you'll have to synchronize in your business logic anyhow to make sure that size() and add() are executed atomically. Hence the synchronization of vector is quite useless in almost any scenario (contrary to some claims on modern JVMs the performance hit of an uncontended lock is completely negligible though, but the Collections API is much nicer so why not use it)
In The Beginning (Java 1.0) there was the "synchronized vector".
Which entailed a potentially HUGE performance hit.
Hence the addition of "ArrayList" and friends in Java 1.2 onwards.
Your code illustrates the rationale for making vectors synchronized in the first place. But it's simply unnecessary most of the time, and better done in other ways most of the rest of the time.
IMHO...
PS:
An interesting link:
http://www.coderanch.com/t/523384/java/java/ArrayList-Vector-size-incrementation
Vectors are Thread safe. ArrayLists are not. That is why ArrayList is faster than the vector.
The below link has nice info about this.
http://www.javaworld.com/javaworld/javaqa/2001-06/03-qa-0622-vector.html
I'm trying to understand the difference in behaviour of an ArrayList
and a Vector
Vector is synchronized while ArrayList is not. ArrayList is not thread-safe.
Does the following snippet in any way illustrate the difference in
synchronization ?
No difference since only Vector is sunchronized
I'm creating a Swing application to make a Game with. It creates images in random locations off the screen and when they leave the screen I would like to remove them. Please take a look at the code snippet:
public void checkTrolls(){ //CAUSES EXCEPTION ERROR WHEN SPRITE EXIT SCREEN
for(AutomatedSprite a : trolls){
if(a.getX() < 0 - a.getImage().getWidth())
trolls.remove(a);
if(a.getY() < 0 - a.getImage().getWidth())
trolls.remove(a);
if(a.getX() > 800)
trolls.remove(a);
if(a.getY() > 600)
trolls.remove(a);
}
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while(true){
dodger.update(); //update sprite
if(trolls.size() != 6){
trolls.add(new AutomatedSprite("images/troll_face.png"));
}
for(Sprite troll : trolls){
troll.update(); //UPDATES MY SPRITES
}
checkTrolls(); //CHECKS TROLLS EXITING THE SCREEN
repaint();
for(Sprite troll : trolls){
System.out.println("X: " + troll.getX());
System.out.println("Y: " + troll.getY());
}
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = timeDiff - DELAY;
if(sleep < 0)
sleep = 5;
try {
Thread.sleep(sleep);
} catch (InterruptedException e) { e.printStackTrace(); }
beforeTime = System.currentTimeMillis();
}
}
trolls is a Vector of AutomatedSprites, when they leave the screen I get a ConcurrentModificationException, apparently I can't remove the instances from my vector.
So it seems that I can't remove anything from the vector while the thread is updating all my sprites, is there a way to pause my thread so I can remove the sprite?
P.S: here is the entire class in case I missed something: Pastebin
You cannot remove from a collection while iterating over it, this is true for a single threaded environment as well as a multithreaded one. syncrhonized will still cause the issue, Thread.sleep too. Use and Iterator and remove that way.
public void checkTrolls(){
for(Iterator<AutomatedSprite> itr = trolls.iterator(); itr.hasNext();){
AutomatedSpring nextElemnt = itr.next();
if(youShouldRemoveTheSprite){
itr.remove();
}
}
}
So here you use the Iterator supplied by your trolls collection. And you are asking the Iterator to safely remove the object from the collection.
Now if you are executed checkTrolls with multiple threads then you will need to synchronize. You can do that like this
public synchronized void checkTrolls(){ ...
Edit based on your recent comment/link.
It isn't so much you assigning the Iterator.next() to a variable, its that you are invoking iterator.next() many times. Each time you invoke next() you are moving the iterator to the List's next element. So at the end of one loop iteration you move the iterator to the 6'th element in the list. If you were indexing it instead it would look like:
for(Iterator<AutomatedSprite> itr = trolls.iterator(); itr.hasNext(); ){
if(trolls.get(0).getX() < 0 - trolls.get(1).getImage().getWidth() ||
trolls.get(2).getY() < 0 - trolls.get(3).getImage().getWidth() ||
trolls.get(4).getX() > 800 ||
trolls.get(5).getY() > 600){
trolls.remove(trolls.get(5));
}
Note for this example: indexing at 0,1,2,3,4... is only for demonstration, in practice it would be i = 0; start for loop trolls.get(i++).getX(), trolls.get(i++).getY() and so forth. If your list was 10,000 you would eventually get a NoSuchElementException
So for example, if you only have 3 trolls, once you get to the 4th itr.next() you'll get a NoSuchElementException. For that reason you'll want to store the next() element in a variable and work on that variable so the itr.hasNext(); returns correctly and the itr.remove() too works correctly.
In checkTrolls() you are removing elements from your Vector as you iterate over it. This will cause a ConcurrentModificationException
From Vector's javadoc
The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the vector is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException.
A couple alternatives:
Create a list of elements to remove and remove them after iterating fully.
Use a thread safe List implementation such as CopyOnWriteArrayList
Have your code inside run method in synchronized block. synchronized will make sure only one thread executing your code at a time.
run(){
synchronized(this){
....your code.
}}
You may make run() also synchronized.
A simple and somewhat naive solution would be too simply synchronize on the trolls collection. If you do this, make sure to yield in the Animator thread to give your checkTrolls function a chance to do processing and cleanup.
I think the problem might be that in 'checkTrolls' you're trying to modify a vector over which you're iterating.
I am wondering if it is possible to avoid the lost update problem, where multiple threads are updating the same date, while avoiding using synchronized(x) { }.
I will be doing numerous adds and increments:
val++;
ary[x] += y;
ary[z]++;
I do not know how Java will compile these into byte code and if a thread could be interrupted in the middle of one of these statements blocks of byte code. In other words are those statements thread safe?
Also, I know that the Vector class is synchronized, but I am not sure what that means. Will the following code be thread safe in that the value at position i will not change between the vec.get(i) and vec.set(...).
class myClass {
Vector<Integer> vec = new Vector<>(Integer);
public void someMethod() {
for (int i=0; i < vec.size(); i++)
vec.set(i, vec.get(i) + value);
}
}
Thanks in advance.
For the purposes of threading, ++ and += are treated as two operations (four for double and long). So updates can clobber one another. Not just be one, but a scheduler acting at the wrong moment could wipe out milliseconds of updates.
java.util.concurrent.atomic is your friend.
Your code can be made safe, assuming you don't mind each element updating individually and you don't change the size(!), as:
for (int i=0; i < vec.size(); i++) {
synchronized (vec) {
vec.set(i, vec.get(i) + value);
}
}
If you want to add resizing to the Vector you'll need to move the synchronized statement outside of the for loop, and you might as well just use plain new ArrayList. There isn't actually a great deal of use for a synchronised list.
But you could use AtomicIntegerArray:
private final AtomicIntegerArray ints = new AtomicIntegerArray(KNOWN_SIZE);
[...]
int len = ints.length();
for (int i=0; i<len; ++i) {
ints.addAndGet(i, value);
}
}
That has the advantage of no locks(!) and no boxing. The implementation is quite fun too, and you would need to understand it do more complex update (random number generators, for instance).
vec.set() and vec.get() are thread safe in that they will not set and retrieve values in such a way as to lose sets and gets in other threads. It does not mean that your set and your get will happen without an interruption.
If you're really going to be writing code like in the examples above, you should probably lock on something. And synchronized(vec) { } is as good as any. You're asking here for two operations to happen in sync, not just one thread safe operation.
Even java.util.concurrent.atomic will only ensure one operation (a get or set) will happen safely. You need to get-and-increment in one operation.