In my java program I have a for-loop looking roughly like this:
ArrayList<MyObject> myList = new ArrayList<MyObject>();
putThingsInList(myList);
for (int i = 0; i < myList.size(); i++) {
doWhatsoever();
}
Since the size of the list isn't changing, I tried to accelerate the loop by replacing the termination expression of the loop with a variable.
My idea was: Since the size of an ArrayList can possibly change while iterating it, the termination expression has to be executed each loop cycle. If I know (but the JVM doesn't), that its size will stay constant, the usage of a variable might speed things up.
ArrayList<MyObject> myList = new ArrayList<MyObject>();
putThingsInList(myList);
int myListSize = myList.size();
for (int i = 0; i < myListSize; i++) {
doWhatsoever();
}
However, this solution is slower, way slower; also making myListSize final doesn't change anything to that! I mean I could understand, if the speed didn't change at all; because maybe JVM just found out, that the size doesn't change and optimized the code. But why is it slower?
However, I rewrote the program; now the size of the list changes with each cycle: if i%2==0, I remove the last element of the list, else I add one element to the end of the list. So now the myList.size() operation has to be called within each iteration, I guessed.
I don't know if that's actually correct, but still the myList.size() termination expression is faster than using just a variable that remains constant all the time as termination expression...
Any ideas why?
Edit (I'm new here, I hope this is the way, how to do it)
My whole test program looks like this:
ArrayList<Integer> myList = new ArrayList<Integer>();
for (int i = 0; i < 1000000; i++)
{
myList.add(i);
}
final long myListSize = myList.size();
long sum = 0;
long timeStarted = System.nanoTime();
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < myList.size(); j++)
{
sum += j;
if (j%2==0)
{
myList.add(999999);
}
else
{
myList.remove(999999);
}
}
}
long timeNeeded = (System.nanoTime() - timeStarted)/1000000;
System.out.println(timeNeeded);
System.out.println(sum);
Performance of the posted code (average of 10 executions):
4102ms for myList.size()
4230ms for myListSize
Without the if-then-else statements (so with constant myList size)
172ms for myList.size()
329ms for myListSize
So the speed different of both versions is still there. In the version with the if-then-else parts the percentaged differences are of course smaller because a lot of the time is invested for the add and remove operations of the list.
The problem is with this line:
final long myListSize = myList.size();
Change this to an int and lo and behold, running times will be identical. Why? Because comparing an int to a long for every iteration requires a widening conversion of the int, and that takes time.
Note that the difference also largely (but probably not completely) disappears when the code is compiled and optimised, as can be seen from the following JMH benchmark results:
# JMH 1.11.2 (released 7 days ago)
# VM version: JDK 1.8.0_51, VM 25.51-b03
# VM options: <none>
# Warmup: 20 iterations, 1 s each
# Measurement: 20 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
...
# Run complete. Total time: 00:02:01
Benchmark Mode Cnt Score Error Units
MyBenchmark.testIntLocalVariable thrpt 20 81892.018 ± 734.621 ops/s
MyBenchmark.testLongLocalVariable thrpt 20 74180.774 ± 1289.338 ops/s
MyBenchmark.testMethodInvocation thrpt 20 82732.317 ± 749.430 ops/s
And here's the benchmark code for it:
public class MyBenchmark {
#State( Scope.Benchmark)
public static class Values {
private final ArrayList<Double> values;
public Values() {
this.values = new ArrayList<Double>(10000);
for (int i = 0; i < 10000; i++) {
this.values.add(Math.random());
}
}
}
#Benchmark
public double testMethodInvocation(Values v) {
double sum = 0;
for (int i = 0; i < v.values.size(); i++) {
sum += v.values.get(i);
}
return sum;
}
#Benchmark
public double testIntLocalVariable(Values v) {
double sum = 0;
int max = v.values.size();
for (int i = 0; i < max; i++) {
sum += v.values.get(i);
}
return sum;
}
#Benchmark
public double testLongLocalVariable(Values v) {
double sum = 0;
long max = v.values.size();
for (int i = 0; i < max; i++) {
sum += v.values.get(i);
}
return sum;
}
}
P.s.:
My idea was: Since the size of an ArrayList can possibly change while
iterating it, the termination expression has to be executed each loop
cycle. If I know (but the JVM doesn't), that its size will stay
constant, the usage of a variable might speed things up.
Your assumption is wrong for two reasons: first of all, the VM can easily determine via escape analysis that the list stored in myList doesn't escape the method (so it's free to allocate it on the stack for example).
More importantly, even if the list was shared between multiple threads, and therefore could potentially be modified from the outside while we run our loop, in the absence of any synchronization it is perfectly valid for the thread running our loop to pretend those changes haven't happened at all.
As always, things are not always what they seem...
First things first, ArrayList.size() doesn't get recomputed on every invocation, only when the proper mutator is invoked. So calling it frequently is quite cheap.
Which of these loops is the fastest?
// array1 and array2 are the same size.
int sum;
for (int i = 0; i < array1.length; i++) {
sum += array1[i];
}
for (int i = 0; i < array2.length; i++) {
sum += array2[i];
}
or
int sum;
for (int i = 0; i < array1.length; i++) {
sum += array1[i];
sum += array2[i];
}
Instinctively, you would say that the second loop is the fastest since it doesn't iterate twice. However, some optimizations actually cause the first loop to be the fastest depending, for instance, on memory walking strides that cause a lot of memory cache misses.
Side-note: this compiler optimization technique is called loop
jamming.
This loop:
int sum;
for (int i = 0; i < 1000000; i++) {
sum += list.get(i);
}
is not the same as:
// Assume that list.size() == 1000000
int sum;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
}
In the first case, the compile absolutely knows that it must iterate a million times and puts the constant in the Constant Pool, so certain optimizations can take place.
A closer equivalent would be:
int sum;
final int listSize = list.size();
for (int i = 0; i < listSize; i++) {
sum += list.get(i);
}
but only after the JVM has figured out what the value of listSize is. The final keyword gives the compiler/run-time certain guarantees that can be exploited. If the loop runs long enough, JIT-compiling will kick in, making execution faster.
Because this sparked interest in me I decided to do a quick test:
public class fortest {
public static void main(String[] args) {
long mean = 0;
for (int cnt = 0; cnt < 100000; cnt++) {
if (mean > 0)
mean /= 2;
ArrayList<String> myList = new ArrayList<String>();
putThingsInList(myList);
long start = System.nanoTime();
int myListSize = myList.size();
for (int i = 0; i < myListSize; i++) doWhatsoever(i, myList);
long end = System.nanoTime();
mean += end - start;
}
System.out.println("Mean exec: " + mean/2);
}
private static void doWhatsoever(int i, ArrayList<String> myList) {
if (i % 2 == 0)
myList.set(i, "0");
}
private static void putThingsInList(ArrayList<String> myList) {
for (int i = 0; i < 1000; i++) myList.add(String.valueOf(i));
}
}
I do not see the kind of behavior you are seeing.
2500ns mean execution time over 100000 iterations with myList.size()
1800ns mean execution time over 100000 iterations with myListSize
I therefore suspect that it's your code that is executed by the functions that is at fault. In the above example you can sometimes see faster execution if you only fill the ArrayList once, because doWhatsoever() will only do something on the first loop. I suspect the rest is being optimized away and significantly drops execution time therefore. You might have a similar case, but without seeing your code it might be close to impossible to figure that one out.
There is another way to speed up the code using for each loop
ArrayList<MyObject> myList = new ArrayList<MyObject>();
putThingsInList(myList);
for (MyObject ob: myList) {
doWhatsoever();
}
But I agree with #showp1984 that some other part is slowing the code.
Related
I ran this segment of code: (outer loop runs 100 times, inner loop runs 1 billion times.)
long l = 0;
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000000000; j++)
l++;
System.out.println(l);
This took around 11-12 seconds when I ran it.
Then I ran this segment of code:
long l = 0;
int i = 0, j = 0;
for(; i < 100; i++)
for(; j < 1000000000; j++)
l++;
System.out.println(l);
and this took about 100 ms (0.1 seconds) whenever I ran it.
Does anyone have any idea why there's a big difference? My theory is that for every value of 'i', the inner for loop has to initialize j again, which gives it more operations to do, so it makes sense that it takes longer. However, the difference is huge (by about 100 times), and with other similar tests, the same thing doesn't happen.
If you want to see it yourself, this is how I timed it:
class Main {
static long start, end;
public static void main(String[] args) {
start();
long l = 0;
int i = 0, j = 0;
for(; i < 100; i++)
for(; j < 1000000000; j++)
l++;
System.out.println(l);
end();
print();
}
public static void start() {
start = System.currentTimeMillis();
}
public static void end() {
end = System.currentTimeMillis();
}
public static void print() {
System.out.println((end - start) + " ms.");
}
}
The second function only iterates through j for the first iteration of I. At that point j exceeds the limit of the for loop and is never run again as it is not reset on the next iteration of i
In your first example, inner loop is running from 0 to 1000000000 for each value of i because we are initializing j=0 for each value of i.
In your second example, inner loop is running from 0 to 1000000000 only for i = 0 because here we are initializing j=0 only for the first iteration of the outer loop (i.e i=0).
Real reason is in second case loop is not running as same as first code.
In first code every time you go inside you start j. With 0
But in second code j will be 1 billion in first iteration. After that It always be 1billoin. Which means second loop condition is failing every time. Second loop will not run more than once.
The two versions are not "almost exactly the same". In fact, they are completely different.
The clue is that they print different values for l:
/tmp$ java Main1.java
1000000000
12 ms.
/tmp$ java Main2.java
100000000000
857 ms.
Clearly one version is doing 100 times more iterations than the other. #Oli's answer explains why.
My theory is that for every value of i, the inner for loop has to initialize j again, which gives it more operations to do, so it makes sense that it takes longer.
Nope. That would not explain a 100 times performance difference. It is not plausible that 100 initializations of an int variable would take (on my machine) 800+ milliseconds.
The real explanation is that you are comparing computations that are NOT comparable.
j is set to 0 outside it's for loop. It is never reset back to 0 on i's next iteration.
1. Suppose following situations.
First:
int x;
for (int i = 0; i < MAX; i++){
// some magic with x
System.out.println(x);
}
Second:
for (int i = 0; i < MAX; i++){
int x;
// some magic with x
System.out.println(x);
}
So which piece of code is better and more efficient?
2. Another two situations.
First:
int size = array.length;
for (int i = 0; i < size; i++) {
// do something with array[i]
}
Second:
for (int i = 0; i < array.length; i++) {
// do something with array[i]
}
Is it more efficient to save array length to variable?
length is just a property in the array object, it doesn't take any time in getting the length.
It is the same as reading from a variable it doesn't need to loop over the whole array to get the length.
And the first two are just scopes.
Local - only available within the loop.
Global - available throught.
Assume you want remainders of numbers when divided by 2.
for(int i = 0; i < 10; ++i)
{
int remainder = i % 2;
System.out.println(remainder);
}
And assume calculating the sum of first 10 natural numbers.
int sum = 0;
for(int i = 0; i <= 10; ++i)
{
//declaring sum here doesnt make sense
sum += i;
}
System.out.println(sum);//sum is available here.
PS: you could just the sum of n natural numbers formula.
1. What you should be more concerned with here, is not efficiency, but scope. Generally, you should strive to keep your variables as locally scoped as possible. This means, if you only need x within the loop, you should define it within the loop.
You get a number of benefits with keeping your variables as locally scoped as possible:
Your code will be much more readable to someone else
You won't accidentally assign to, or use the value of a variable you defined further up in your code that is still in scope, thus minimizing errors in your program
Most importantly, the garbage collector will free up any memory used by the variable as soon as it goes out of scope, keeping your program's performance high, and memory usage low.
You can read up more on variable scope and best practices from Josh Bloch's excellent book, "Effective Java" (scope is discussed in items 13 and 45). You might also want to read item 55, which discusses why it is important to optimize judiciously.
2. For the second part of your question, see The Skeet's answer here.
Here's an example:
public static void main(String[] args) {
for(int i=0; i<getSize(); i++) {
System.out.println("i: " + i);
}
}
private static int getSize() {
int size = new Random().nextInt(10);
System.out.println("size: " + size);
return size;
}
This outputs:
size: 2
i: 0
size: 4
i: 1
size: 4
i: 2
size: 8
i: 3
size: 0
Notice how getSize() is called for every iteration of the loop. In your example, calling .length won't make a huge difference, as the JIT runtime will know how to optimize this call. But imagine getSize() was a more complex operation, like counting the number of rows in a database table. Your code will be super slow as every iteration of the loop will call getSize(), resulting in a database roundtrip.
This is when you would be better off evaluating the value before hand. You can do this and still retain minimal scope for size, like this:
public static void main(String[] args) {
for(int size = getSize(), i=0; i<size; i++) {
System.out.println("i: " + i);
}
}
private static int getSize() {
int size = new Random().nextInt(10);
System.out.println("size: " + size);
return size;
}
size: 5
i: 0
i: 1
i: 2
i: 3
i: 4
Notice how getSize() is only called once, and also, the size variable is only available inside the loop and goes out of scope as soon as the loop completes.
Consider the two following code samples. All benchmarking is done outside of the container being used to calculate an average of the sampled execution times. On my machine, running Windows 7 and JDK 1.6, I am seeing the average execution time in example 2 close to 1,000 times slower than that of example 1. The only explanation I can surmise is that the compiler is optimizing some code used by LinkedList to the detriment of everything else. Can someone help me understand this?
Example 1: Using Arrays
public class TimingTest
{
static long startNanos, endNanos;
static long[] samples = new long[1000];
public static void main(String[] args)
{
for (int a = 0; a < 100; a++)
{
for (int numRuns = 0; numRuns < 1000; numRuns++)
{
startNanos = System.nanoTime();
long sum = 0;
for (long i = 1; i <= 500000; i++)
{
sum += i % 13;
}
endNanos = System.nanoTime() - startNanos;
samples[numRuns] =(endNanos);
}
long avgPrim = 0L;
for (long sample : samples)
{
avgPrim += sample;
}
System.out.println("Avg: " + (avgPrim / samples.length) );
}
}
}
Example 2: Using a LinkedList
public class TimingTest
{
static long startNanos, endNanos;
static List<Long> samples = new LinkedList<Long>();
public static void main(String[] args)
{
for (int a = 0; a < 100; a++)
{
for (int numRuns = 0; numRuns < 1000; numRuns++)
{
startNanos = System.nanoTime();
long sum = 0;
int index = 0;
for (long i = 1; i <= 500000; i++)
{
sum += i % 13;
}
endNanos = System.nanoTime() - startNanos;
samples.add(endNanos);
}
long avgPrim = 0L;
for (long sample : samples)
{
avgPrim += sample;
}
System.out.println("Avg: " + (avgPrim / samples.size()));
}
}
}
Something is very wrong here: When I run the array version, I get an average execution time of 20000 nanoseconds. It is downright impossible for my 2 GHz CPU to execute 500000 loop iterations in that time, as that would imply the average loop iteration to take 20000/500000 = 0.04 ns, or 0.08 cpu cpu cycles ...
The main reason is a bug in your timing logic: In the array version, you do
int index = 0;
for every timing, hence
samples[index++] =(endNanos);
will always assign to first array element, leaving all others at their default value of 0. Hence when you take the average of the array, you get 1/1000 of the last sample, not the average of all samples.
Indeed, if you move the declaration of index outside the loop, no significant difference is reported between the two variants.
Here's a real run of your code (renamed classes for clarity, and cut the outside for loop in each to a < 1 for time's sake):
$ for f in *.class
do
class=$(echo $f | sed 's`\(.*\)\.class`\1`')
echo Running $class
java $class
done
Running OriginalArrayTimingTest
Avg: 18528
Running UpdatedArrayTimingTest
Avg: 41111273
Running LinkedListTimingTest
Avg: 41340483
Obviously, your original concern was caused by the typo #meriton pointed out, which you corrected in your question. We can see that, for your test case, both and array and a LinkedList behave almost identically. Generally speaking, insertions on a LinkedList are very fast. Since you updated your question with meriton's changes, but didn't update your claim that the former is dramatically faster than the latter, it's no longer clear what you're asking; however I hope you can see now that in this case, both data structures behave reasonably similarly.
What is the best way to loop through an array when you need the index?
Option 1:
int len = array.length;
for (int i = 0; i < len; ++i) {
array[i] = foo(i);
}
Option 2:
for (int i = 0; i < array.length; i++) {
array[i] = foo(i);
}
Or, does it not matter? Or is there a better way to do it?
Just to point out the differences: In one case, the length of the array is evaluated as part of the test in the loop, although the compiler should normally optimize that.
Secondly, is ++i any different here from i++? I definitely prefer ++i if it is C++ but am not sure for Java.
i++ vs ++i does not matter in this particular case. While C masters will tell you to store array.length in a variable, modern optimizing compilers make that unnecessary in this case as long as the length does not change in the loop. If you're really concerned you can benchmark both, but since .length doesn't actually need to traverse the entire array each time you'll be OK.
Generally those two methods are equivalent. You should note that in
for (int i = 0 ; i < foo() ; i++) {
...
}
the foo() is called once before each iteration (as opposed to only once before the first iteration), so you might want to take this into account for more complicated situations by perhaps doing something like
int n = foo();
for (int i = 0 ; i < n ; i++) {
...
}
which is analogous to your Option 1. So I would say Option 1 is certainly the safer of the two, but most of the time it should not make a significant difference which you use.
As for your second question: ++i first increments your variable and then retrieves it's value, i++ first retrieves the value and then increments. Just try these two pieces of code:
int i = 0;
System.out.println(++i);
------------------------
int i = 0;
System.out.println(i++);
The first prints 1 but the second prints 0. Of course when ++i and i++ are alone it makes no difference.
for whether to use "array.length" in for loop:
Generally the compiler will do some optimization, as a result it is equivalent to using a variable in the for loop
for "i++" and "++i"
In C++, ++i is preferred and more efficient, but in Java, they are equivalent in this case.
In addition to arshaji response I wanted to know if there was a performance benefit of using size() in a loop vs storing it in advance. I believe the result show that the compiler does optimize things and accessing the length of a list is the same as accessing a variable ( I was worried that the fact it had to go through a function would slow down things).
Here is the time it takes for those two for different method of loop:
for(long i = 0 ; i < mylist.size(); i++){}
VS
for(long i = 0 ; i < 10_000_000; i++){}
Here is the result for a list of ten million elems:
fixed length:
,162,157,151,157,156,159,157,149,150,170,158,153,152,158,151,151,156,156,151,153
getSize:
,164,156,159,154,151,160,162,152,154,152,151,149,168,156,152,150,157,150,156,157
import java.util.ArrayList;
import java.util.List;
public class Main {
final static int LENGTH_SAMPLE = 20;
final static long LENGTH = 10_000_000;
public static void main(String[] args) {
List<Long> mylist = new ArrayList<>();
for(long i = 0 ; i < LENGTH; i++){
mylist.add(i);
}
System.out.println("fixed length:");
for(int i = 0 ; i < LENGTH_SAMPLE; i++){
System.out.printf("," + fixedSize(mylist));
}
System.out.println("");
System.out.println("getSize:");
for(int i = 0 ; i < LENGTH_SAMPLE; i++){
System.out.printf("," + fctSize(mylist));
}
}
private static long fixedSize(List list){
long start = System.currentTimeMillis();
for(long i = 0 ; i < LENGTH; i++){
System.currentTimeMillis();
}
return System.currentTimeMillis() - start;
}
private static long fctSize(List list){
long start = System.currentTimeMillis();
for(long i = 0 ; i < list.size(); i++){
System.currentTimeMillis();
}
return System.currentTimeMillis() - start;
}
}
Assume i have the following code, there are three for loop to do something. Would it run fast if i change the most outer for loop to while loop? thanks~~
int length = 200;
int test = 0;
int[] input = new int[10];
for(int i = 1; i <= length; i++) {
for (int j = 0; j <=length - i; j++) {
for (int k = 0; k < length - 1; k++) {
test = test + input[j + k];
}
}
}
No, changing the type of loop wouldn't matter.
The only thing that can make it faster would be to have less nesting of loops, and looping over less values.
The only difference between a for loop and a while loop is the syntax for defining them. There is no performance difference at all.
int i = 0;
while (i < 20){
// do stuff
i++;
}
Is the same as:
for (int i = 0; i < 20; i++){
// do Stuff
}
(Actually the for-loop is a little better because the i will be out of scope after the loop while the i will stick around in the while loop case.)
A for loop is just a syntactically prettier way of looping.
This kind of micro-optimization is pointless.
A while-loop won’t be faster.
The loop structure is not your bottleneck.
Optimize your algorithm first.
Better yet, don’t optimize first. Only optimize after you have found out that you really have a bottleneck in your algorithm that is not I/O-dependant.
Someone suggested to test while vs for loops, so I created some code to test whether while loops or for loops were faster; on average, over 100,000 tests, while loop was faster ~95% of the time. I may have coded it incorrectly, I'm quite new to coding, also considering if I only ran 10,000 loops they ended up being quite even in run duration.
edit I didn't shift all the array values when I went to test for more trials. Fixed it so that it's easier to change how many trials you run.
import java.util.Arrays;
class WhilevsForLoops {
public static void main(String[] args) {
final int trials = 100; //change number of trials
final int trialsrun = trials - 1;
boolean[] fscount = new boolean[trials]; //faster / slower boolean
int p = 0; // while counter variable for for/while timers
while (p <= trialsrun) {
long[] forloop = new long[trials];
long[] whileloop = new long[trials];
long systimeaverage;
long systimenow = System.nanoTime();
long systimethen = System.nanoTime();
System.out.println("For loop time array : ");
for (int counter=0;counter <= trialsrun; counter++) {
systimenow = System.nanoTime();
System.out.print(" #" + counter + " #");
systimethen = System.nanoTime();
systimeaverage = (systimethen - systimenow);
System.out.print( systimeaverage + "ns |");
forloop[counter] = systimeaverage;
}
int count = 0;
System.out.println(" ");
System.out.println("While loop time array: ");
while (count <= trialsrun) {
systimenow = System.nanoTime();
System.out.print(" #" + count + " #");
systimethen = System.nanoTime();
systimeaverage = (systimethen - systimenow);
System.out.print( systimeaverage + "ns |");
whileloop[count] = systimeaverage;
count++;
}
System.out.println("===============================================");
int sum = 0;
for (int i = 0; i <= trialsrun; i++) {
sum += forloop[i];
}
System.out.println("for loop time average: " + (sum / trials) + "ns");
int sum1 = 0;
for (int i = 0; i <= trialsrun; i++) {
sum1 += whileloop[i];
}
System.out.println("while loop time average: " + (sum1 / trials) + "ns");
int longer = 0;
int shorter = 0;
int gap = 0;
sum = sum / trials;
sum1 = sum1 / trials;
if (sum1 > sum) {
longer = sum1;
shorter = sum;
}
else {
longer = sum;
shorter = sum1;
}
String longa;
if (sum1 > sum) {
longa = "~while loop~";
}
else {
longa = "~for loop~";
}
gap = longer - shorter;
System.out.println("The " + longa + " is the slower loop by: " + gap + "ns");
if (sum1 > sum) {
fscount[p] = true; }
else {
fscount[p] = false;
}
p++;
}
int forloopfc=0;
int whileloopfc=0;
System.out.println(Arrays.toString(fscount));
for(int k=0; k <= trialsrun; k++) {
if (fscount[k] == true) {
forloopfc++; }
else {
whileloopfc++;}
}
System.out.println("--------------------------------------------------");
System.out.println("The FOR loop was faster: " + forloopfc + " times.");
System.out.println("The WHILE loop was faster: " + whileloopfc + " times.");
}
}
you cant optimize it by changing it to while.
you can just increment speed very very very very little by changing the line
for (int k = 0; k < length - 1; k++) {
by
for (int k = 0; k < lengthMinusOne; k++) {
where lengthMinusOne is calculated before
this subtraction is just calculating almost (200x201/2) x (200-1) times and it is very little number for computer :)
here's a helpful link to an article on the matter
according to it, the While and For are almost twice as faster but both are the same.
BUT this article was written in 2009 and so i tried it on my machine and here are the results:
using java 1.7: the Iterator was about 20%-30% faster than For and While (which were still the same)
using java 1.6: the Iterator was about 5% faster than For and While (which were still the same)
so i guess the best thing is to just time it on your own version and machine and conclude from that
Even if the hypothesis of the while loop being faster than the for loop were true (and it's not), the loops you'd had to change/optimize wouldn't be the outer ones but the inner ones, because those are executed more times.
The difference between for and while is semantic :
In a while loop, you will loop as long as the condition is true, which can vary a lot, because you might, in your loop, modify variables using in evluating the while condition.
Usually, in a for loop, you loop N time. This N can be variable, but doesn't move until the end of your N loop, as usually developpers doesn't modify variables evaluated in the loop condition.
It is a way to help other to understand your code. You are not obliged not to modify for loop variables, but it is a common (and good) practice.
No, you're still looping the exact same number of times. Wouldn't matter at all.
Look at your algorithm! Do you know beforehand which values from your array are added more than one time?
If you know that you could reduce the number of loops and that would result in better performance.
There would be no performance difference. Try it out!
The JVM and further, the compiler, would make both loops into something like
label:
;code inside your for loop.
LOOP label
It would only matter if you are using multi-thread or multiple processor programming. Then it would also depends on how you assign the loops to the various processors/threads.
No, it's not going to make a big difference, the only thing is that if your nesting loops you might want to consider switching up for example for organizational purposes, you may want to use while loop in the outer and have for statements inside it. This wouldn't affect the performance but it would just make your code look cleaner/organized
You can calculate it yourself.
int length = 200;
int test = 0;
int[] input = new int[10];
long startTime = new Date().getTime();
for(int i = 1; i <= length; i++) {
for (int j = 0; j <=length - i; j++) {
for (int k = 0; k < length - 1; k++) {
test = test + input[j + k];
}
}
}
long endTime = new Date().getTime();
long difference = endTime - startTime;
System.out.println("For - Elapsed time in milliseconds: " + difference);
test = 0;
input = new int[10];
int i = 0, j = 0, k = 0;
startTime = new Date().getTime();
while(i < length) {
while(j <= length - i ) {
while(k < length - 1) {
test = test + input[j + k];
k++;
}
j++;
}
i++;
}
endTime = new Date().getTime();
difference = endTime - startTime;
System.out.println("While - Elapsed time in milliseconds: " + difference);
The for loop and while loop both are iteration statements, but both have their distinct feature.
Syntax
While Loop
//setup counter variable
int counter = 0;
while ( condition) {
//instructions
//update counter variable
counter++; //--> counter = counter + 1;
}
For Loop
for (initialization; condition; iteration){
//body of for loop
}
The for loop does have all its declaration (initialization, condition, iteration) at the top of the body of the loop. Adversely, in a while loop only initialization and condition are at the top of the body of the loop and iteration may be written anywhere in the body of the loop.
Key Differences Between for and while loop
In the for loop, initialization, condition checking, and increment or decrement of iteration variable are done explicitly in the syntax of a loop only. As against, in the While loop, we can only initialize and check conditions in the syntax of the loop.
When we are aware of the number of iterations that have to occur in the execution of a loop, then we use for loop. On the other hand, if we are not aware of the number of iteration that has to occur in a loop, then we use a while loop.
If you fail to put the condition statement in the for loop, it will lead to an infinite iteration of a loop. In contrast, if you fail to put a condition statement in the while loop it will lead to a compilation error.
The initialization statement in the syntax of the for loop executes only once at the start of the loop. Conversely, if the while loop is carrying an initialization statement in its syntax, then the initialization statement in the while loop will execute each time the loop iterates.
The iteration statement in the for loop will execute after the body for loop executes. On the contrary, the iteration statement can be written anywhere in the body of the while loop so, there can be some statements that execute after the execution of the iteration statement in the body of the `while loop.
Based on this: https://jsperf.com/loops-analyze (not created by me) the while loop is 22% slower than a for loop in general. At least in Javascript it is.