Could you tell me, what is the difference between For Loop Java in Code A and B? while both of them gives a same result in executing? and i know what they are doing, but why is For loop written this way in the code *A*
Thanks
The code
//Code A
public class MyArray {
public static void main (String[] args){
int[] a ={1,10,30,40,50};
for (int i : a)
{
System.out.println(i);
}
}
}
//====================================
//Code B
public class MyArray{
public static void main (String[] args){
int[] a ={1,10,30,40,50};
for (int i=0;i< a.length; i++)
{
System.out.println(a[i]);
}
}
}
Iterating over a collection is uglier than it needs to be. Consider the following method, which takes a collection of timer tasks and cancels them:
void cancelAll(Collection<TimerTask> c) {
for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); )
i.next().cancel();
}
The iterator is just clutter. Furthermore, it is an opportunity for error. The iterator variable occurs three times in each loop: that is two chances to get it wrong. The for-each construct gets rid of the clutter and the opportunity for error. Here is how the example looks with the for-each construct:
void cancelAll(Collection<TimerTask> c) {
for (TimerTask t : c)
t.cancel();
}
for each is just a better way of iterating.
Limitation:
in for-each loop you will not be able to know which number of element(index of the element in collection) you are processing, you need to define counter for the same, while in simple for loop i tells you the number of the element you are processing.
Code A by is just syntactic sugar for code B and works on Java versions 5 or later.
The advantage is that you do not have to handle the mundane indexing code on your own.
Code A is also known as the foreach loop
Plus Code A also works if instead of int[] you had a Collection, thus giving you a uniform way of iterating over arrays and collections (or to be ever more precise, any subclass of Iterable)
Practically, no difference, but code A is easier to read and harder to make a mistake.
The shorter version of the for loop means for each index in the array, which quite simply is easier to understand.
The other for loop is a most commonly used which starts from a assigned starting value and goes on till the end of array.
The selection depends on the situation according to me. There might be a time when using the codeA format would give a better understanding to the one who debugging the application.
The answers here have not pointed to a certain vital difference: in code A, you cannot simply change the elements of the array, because the i is just a reference, while in code B, you can do a[i] = //something.
If your array was an array of some Objects and you just wanted to use Mutability, then there is no difference.
Actually both codes are equal as first code if in the right-hand side of the for(:) array rather than an Iterable object (as in this case), the internal code uses an int index counter and checks against array.length. which is equivalent to:
for (int i=0;i< a.length; i++)
{
System.out.println(a[i]);
}
Advantage of first code is its internally handle the end condition and short in writing then the second one.
but if object is iterable then it converts to:
for(Iterator<String> i = iteratableObject.iterator(); i.hasNext(); ) {
String item = i.next();
System.out.println(item);
}
Related
I have written 2 methods in Java. Second method looks cleaner to me because I come from python background, but I think it will be slower than first because indexOf() also does the iteration? Is there a way to use for in loop correctly in situation like this? Also, if there is better way to do it (without Streams), how can it be done?
private ArrayList<MyObject> myObjects;
First method:
private int findObject(String objectName) {
for(int i=0; i<this.myObjects.size(); i++) {
MyObject myObject = this.myObjects.get(i);
if(myObject.getName().equals(objectName)) return i;
}
return -1;
}
Second method:
private int findObject(String objectName) {
for(MyObject myObject: this.myObjects) {
if(myObject.getName().equals(objectName)) return this.myObjects.indexOf(myObject);
}
return -1;
}
I think it will be slower than first because indexOf() also does the iteration?
You are correct.
Is there a way to use for each loop correctly in situation like this?
You can use a for each AND an index variable.
private int findObject(String objectName) {
int i = 0;
for (MyObject myObject: this.myObjects) {
if (myObject.getName().equals(objectName)) return i;
i++;
}
return -1;
}
This would be a good solution if myObjects.get(i) is an expensive operation (e.g. on a LinkedList where get(n) is O(N)) or if it is not implementable (e.g. if you were iterating a Stream).
You could also use a ListIterator provided that myObjects has a method that returns a ListIterator; see #Andy Turner's answer for an example. (It won't work for a typical Set or Map class.)
The first version is perfect if you know you're working with an ArrayList (or some other array-based List, e.g. Vector).
If myObject happens to be a LinkedList or similar, your performance will degrade with longer lists, as then get(i) no longer executes in constant time.
Your second approach will handle LinkedLists as well as ArrayLists, but it iterates twice over your list, once in your for loop, and once in the indexOf() call.
I'd recommend a third version: use the for loop from the second approach, and add an integer counting variable, incrementing inside the loop. This way, you get the best of both: iterating without performance degradation, and cheap position-counting.
The better way of doing this (that avoids you having to maintain a separate index variable; and works for non-RandomAccess lists too) would be to use a ListIterator:
for (ListIterator<MyObject> it = myObjects.listIterator(); it.hasNext();) {
MyObject myObject = it.next();
if(myObject.getName().equals(objectName)) return it.prevIndex();
}
return -1;
I'm using
Collections.synchronizedList(new ArrayList<T>())
part of the code is:
list = Collections.synchronizedList(new ArrayList<T>());
public void add(T arg) {
int i;
synchronized (list) {
for (i = 0; i < list.size(); i++) {
T arg2 = list.get(i);
if (arg2.compareTo(arg) < 0) {
list.add(i, arg);
break;
}
}
Is it right that for loop is actually using iterator and therefore I must wrap the for with synchronized?
Is it thread-safe to use synchronized and make addition inside it like I did here?
I'm sorry if these questions are very basic, I'm new to the subject and didn't find answers on the internet.
Thank you!!
Is it right that for loop is actually using iterator and therefore I must wrap the for with synchronized?
There are two parts to your question.
Firstly, no, you're not using an iterator here, this is a basic for loop.
The enhanced for loop is the for loop which uses an iterator:
for (T element : list) { ... }
You can see in the language spec how this uses the iterator - search for where it says "The enhanced for statement is equivalent to a basic for statement of the form".
Secondly, even though you're not using an iterator, you do need synchronized. The two are orthogonal.
You are doing multiple operations (the size, the get and the add), with dependencies between them. You need to make sure that no other thread interferes with your logic:
the get depends on the size, since you don't want to try to get an element with index >= size, for instance;
the add depends on the get, since you're apparently trying to ensure the list elements are ordered. If another thread could sneak in and change the element after you get it, you might insert the new element in the wrong place.
You correctly avoid this potential interference this through synchronization over list, and creating the synchronizedList in such a way that nothing other than the synchronizedList can get direct access to the underlying list.
If your arg2.compareTo(arg) never return 0 (zero) you can use TreeSet. Will be much more simple:
set = Collections.synchronizedSet(new TreeSet<T>());
public void add(T arg) {
set.add(arg);
}
If you need hold same items (compareTo returns 0) then use the list:
list = new ArrayList<T>();
public void add(T arg) {
synchronized (list) {
int index = Collections.binarySearch(list, arg);
list.add(index, arg);
}
}
First and second cases complexity will be log(N) (10 for 1000 items). Your code complexity is N (1000 for 1000 items).
Is this usage of elements of an ArrayList:
for(int i=0; i<array_list.size(); i++){
Object obj = array_list.get(i);
//do **lots** of stuff with **obj**
}
faster than this one:
for(int i=0; i<array_list.size(); i++){
//do **lots** of stuff with **array_list.get(i)**;
}
It depends on how many times array_list.get(i) is called in the second code. If it is called only once, there is no difference between both methods.
If it's invoked multiple times, saving the value in a variable may be more efficient (it depends on the compiler and the JIT optimizations).
Sample scenario where the first method may be more efficient, compiled using Oracle JDK's javac compiler, assuming the list contains String objects:
for(int i=0; i<array_list.size(); i++){
String obj = array_list.get(i);
System.out.println(obj);
if(!obj.isEmpty()) {
String o = obj.substring(1);
System.out.println(o + obj);
}
}
In this case, obj is saved as a local variable and loaded whenever it is used.
for(int i=0; i<array_list.size(); i++){
System.out.println(array_list.get(i));
if(!array_list.get(i).isEmpty()) {
String o = array_list.get(i).substring(1);
System.out.println(o + array_list.get(i));
}
}
In this case, multiple invokation for List.get are observed in the bytecode.
The performance difference between getting once and a local variable is almost always neglible. But... if you insist on doing it the hardcore way, this is the fast way to go:
ArrayList<Object> array_list = ...
// cache list.size() in variable!
for (int i=0, e=array_list.size(); i < e; ++i) {
// get object only once into local variable
Object object = array_list.get(i);
// do things with object
}
It caches the lists size into a local variable e, to avoid invoking array_list.size() at each loop iteration, as well as each element in the loop to avoid get(index) calls. Be aware that whatever you actually do with the objects in the loop will most likely be by orders of magnitude more expensive than the loop itself.
Therefore, prefer code readability and simply use the advanced for loop syntax:
ArrayList<Object> array_list = ...
for (Object object : array_list) {
// do things with object
}
No hassles, short and clear. Thats worth far more than a few saved clock cycles in most cases.
Java has different for-loops to walk through a list. For example:
public void myMethod(List list) {
for (int i = 0; i <= list.size(); i++) {
...
}
}
Or, we can write something like this:
public void myMethod(List list) {
for (String obj : list) {
...
}
}
Or, we can use a list iterator:
public void myMethod(List list) {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
...
}
}
Which one is best and prevents NullPointerExceptions without any more code?
Your second variant is the best (and it's essentially equivalent to your third, but less verbose). The reason it's superior is because you're looping via an Iterator as opposed to calling get() multiple times, as you would have to do with your first variant. For LinkedLists, for instance, get() is an O(n) operation, meaning the first snippet would be O(n2) whereas the second would be O(n).
In the case of null, all three variants will throw a NullPointerException; you should check for null beforehand (or ensure that your list can never be null).
In my opinion, the second form is better because it's shorter. Behind the covers, it does the same as your third form.
None of the forms will prevent null pointer exceptions.
This question already has answers here:
How does the Java 'for each' loop work?
(29 answers)
Closed 7 years ago.
How does a for-each loop works when it calls a method, either recursively or a different method?
Example:
for(String permutation : permute(remaining))
{
// Concatenate the first character with the permutations of the remaining chars
set.add(chars.charAt(i) + permutation);
}
By the way the method permute takes in a String and returns a set.
Thank you.
According to the Java Language Specification for the enhanced for statement, the expression:
for ( FormalParameter : Expression ) Statement
Is executed as follows:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableModifiersopt TargetType Identifier =
(TargetType) #i.next();
Statement
}
Thus, the Expression (which must be of type Iterable) only has its iterator() method called once.
Calls it once, stores the result, does foreach.
Like this:
Collection<String> temp = permute(remaining);
for(String permutation : temp) {
...
}
Edit: If this is recursive, it really makes no difference. Every layer of recursion simply has its own scope, and thus its own "temp" variable. Thus the permute function will recurse to the lowest level, then each higher level will do its completely separate foreach loop successively.
If we compile this Test
class Test {
public static void main(String[] args) throws Exception {
Set<String> set = new HashSet<>();
for (String s : set) {
}
}
}
and decompile Test.class with JAD we will see that javac replaced for-each with this code
Set set = new HashSet();
String s;
for(Iterator iterator = set.iterator(); iterator.hasNext();)
s = (String)iterator.next();
Foreach loop works on any class that implements the Iterable interface, and is only syntax sugar for calling hasNext() and next() on an Iterator. Same thread same loop and the function is called once.
In your example, the result of permute(remaining) is evaluated before one enters into the loop. While the enhanced for loop is really nothing more than syntactic sugar for iterators, it still follows the same principles as other loops would - it has to have a set to operate with before it can do anything else.
A simpler example would be something like this:
while(input.hasNext())
That's something you may see in projects that read in an indefinite amount of lines. The expression input.hasNext() has to be evaluated first, then you may loop.