I just started learning Java and the first thing I came across is the foreach loop, not knowing the way it works the first thing I did was:
int[] array = new int [10];
for (int i: array){
i = 1;
}
And obviously failed to assign 1 to every element of the array. Then I added System.out.print(i); (after i = 1;) to the body of the loop and saw that the output of the screen was 1111111111 but since doing something with i inside the loop is valid that most likely i is a copy of every element of the array, ain't it? (first questions)
If the above is true doesn't this mean that the foreach loop is much slower then the common for loop since it involves making copies of each element of the array? Or since Java doesn't have pointers and pointer arithmetic, the oprator[] may be designed in some other "badly" fashion that copying every element is actually faster?
And if the above assumptions are true, why one would use an obviously slower foreach loop instead of a common forloop?
In short the questions:
Is i the copy of each element of the array? If not what is it
then?
Isn't the foreach loop slower then the common one? If not, how
"badly" is then operator[] designed?
There is nothing more except readability to win in a foreach loop?
In the code
for (int i: array){
You declare a variable i that on each loop iteration gets the value of the next element in the array, it isn't a reference to that element.
In
i = 1;
you assign a new value to the variable, not to the element in the array.
You cannot set the values of array elements with a foreach loop directly. Use a normal for loop for that
for (int i = 0; i < array.length; i++) {
array[i] = ...; // some value
}
In the above example, you are using the declared variable i as an index to the element in the array.
array[i]
is accessing the element itself whose value you can modify.
Ans obviously failed to assign 1 to every element of the array. The I
added System.out.print(i); to the body of the loop and saw that the
output of the screen was 1111111111 but since doing something with i
inside the loop is valid that most likely i is a copy of every element
of the array, ain't it? (first questions)
You must have put the System.out.print(i) after the i = 1, otherwise you would get 0000000.
If the above is true doesn't this mean that the foreach loop is much
slower then the common for loop since it involves making copies of
each element of the array? Or since Java doesn't have pointers and
pointer arithmetic, the oprator[] may be designed in some other
"badly" fashion that copying every element is actually faster?
Have a look here to see how the foreach loop works. For arrays,
for (int i: array){
i = 1;
}
is equivalent to
for (int index = 0; index < array.length; index++) {
int i = array[index];
i = 1;
}
So it isn't slower. You're doing one more primitive creation on the stack.
It depends on the implementation. For arrays, it's not slower in any way. It just serves different purposes.
why one would use an obviously slower foreach loop instead of a common
forloop?
One reason is for readability. Another is when you don't care about changing the element references of the array, but using the current references.
Take a reference type example
public class Foo {
public int a;
}
Foo[] array = new Foo[3];
for (int i = 0; i < array.length; i++) {
array[i] = new Foo();
array[i].a = i * 17;
}
for (Foo foo : array) {
foo.a = 0; // sets the value of `a` in each Foo object
foo = new Foo(); // create new Foo object, but doesn't replace the one in the array
}
With primitive types such a thing doesn't work.
for (int index = 0; index < array.length; index++) {
int i = array[index];
i = 1; // doesn't change array[index]
}
From Item 46 in Effective Java by Joshua Bloch :
The for-each loop, introduced in release 1.5, gets rid of the clutter
and the opportunity for error by hiding the iterator or index variable
completely. The resulting idiom applies equally to collections and
arrays:
// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
doSomething(e);
}
When you see the colon (:), read it as “in.” Thus, the loop above
reads as “for each element e in elements.” Note that there is no
performance penalty for using the for-each loop, even for arrays. In
fact, it may offer a slight performance advantage over an ordinary for
loop in some circumstances, as it computes the limit of the array
index only once. While you can do this by hand (Item 45), programmers
don’t always do so.
Advantages
Readability
It increases the abstraction level - instead of having to express the low-level details of how to loop around a list
or array (with an index or iterator), the developer simply states that
they want to loop and the language takes care of the rest.
Disadvantage:
Cannot access the index or to remove an item.
To sum up,
the enhanced for loop offers
A concise higher level syntax to loop over a list or array which
1.1 improves clarity
1.2 readability.
However, it misses : allowing to access the index loop or to remove an item.
Setting the values by reference didn't work because int is a primitive type. For any kind of Object[] it would work. Making a copy of a primitive type is very fast, and will be done by the processor many times without your realising.
The foreach loop is more readable, but it's also more writeable. A common programmer error is:
for (int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; i++) //oops, incrementing wrong variable!
{
//this will not execute as expected
}
}
It's impossible to make this error using a foreach loop.
The for statement also has another form designed for iteration through Collections and arrays This form is sometimes referred to as the enhanced for statement, and can be used to make your loops more compact and easy to read.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
So, you're right. Readability is the main win here. For further information on the for each loop, or enhanced for loop, here a blog entry from oralce.
The for each utilized the functionality of the Iterable<E> interface, so the performance depends on the implementation.
Related
The following works fine,
int i;
for (i = 0; i < 10; i++) {}
But this doesn't
// a is an ArrayList of Integers
Integer i;
for (i: a) {}
and I'm forced to do it this way:
for (Integer i : a) {}
Why is it that the second loop doesn't work?
Think about it this way: What would happen if you always initialized your variable?
In the first case: It's initialized IN this example, clearly no problem.
In the second case: You initialize it, to say, 1. Now you have a variable, "1", and you throw it into this for loop. "for( 1 : a)". What does that mean?? And if you override the value of "i" for every value in a, then when it comes out of the loop it's simply the last entry in A. Again, what does that really mean? Why would that be useful? How does the effect the rest of the code outside of this loop? It's bad design to support that, it would result in all sorts of crazy, unexpected behavior and unreadable code.
In the third case: Your variable is explicitly declared IN the scope of that loop, and is very clearly temporary. It will do its job of extracting what you need from this array and be done with. Any modifications to outside pieces of code will need to happen intentionally with explicit setters. Note that you can't initialize it here, because initializing is meaningless.
For the for loops, you need 3 statements.
Your second loop only has 2 statements, and your first one has 3. On top of that, you never initialized your integer i. Make sure to do
int i =0;
for(i;i<=10;i++){
}
For enchanced for loops, you must have
for (String element : array) {
System.out.println("Element: " + element);
}
You can check out this link, it might help. What is the syntax of enhanced for loop in Java?
You have to explicitly give the type of object that you are iterating over in the array list. In the first for loop you are just plugging in the index. In the second, you are trying to have the for loop grab the object without knowing what kind of object it is.
The enhanced for statement is equivalent to a basic for statement of the form:
for (Iterator i = Expression.iterator(); i.hasNext(); ) {
TargetType Identifier = (TargetType) i.next();
...
}
14.14.2. The enhanced for statement
This one is normal for loop using. You can declare the variable type outside the for
int i;
for (i = 0; i < 10; i++) {}
or
Integer i;
for (i = 0; i < 10; i++) {
System.out.println(i);
}
the second one, if you would like to use foreach(also known as Enhanced For-loop) with the Generic type, the syntax must be:
for(data_type variable : array | collection){}
Hope this help!
As per JLS (see very bottom of 15.27.2. Lambda Body) - in each iteration of enhanced-for loop we have a brand-new i variable => we cannot reuse (Integer i;) variable declared before the loop.
We have a brand-new variable in each loop, hence we have declaration syntax here: for(Integer i : array) as it is really declared again and again on each iteration.
Proof comes from JLS code example about lambdas:
void m9(String[] arr) {
for (String s : arr) {
foo(() -> s);
// Legal: s is effectively final
// (it is a new variable on each iteration)
}
}
Can anyone explain this code to me?
class className {
int[] coeffs;
int count(int value) {
int count = 0;
for (int coeff: coeffs)
if (coeff == value)
count++;
return count;
}
}
What I really don't understand is this part:
for (int coeff: coeffs)
What is it mean? Thanks for help.
In earlier versions of Java, there was only the C/Fortran style "for()" loop.
Java 5 (JDK 1.5, 2004) introduced a "foreach()" loop, with the syntax you've described:
http://en.wikipedia.org/wiki/Foreach_loop#Java
for (type item: iterableCollection) {
// do something to item
}
It's worth noting that although the newer "foreach" syntax might be more "elegant", the "old" for loop index can actually be faster:
https://www.java.net//node/662136
That is the enhanced for each loop to loop through the array int[] array.
Look at the Oracle documentation
This is a foreach loop - it means that for every value in the array coeffs the code inside the for loop will be executed, with the variable coeff representing the value used during that particular iteration.
That's an enhanced for loop. It is structured as follows:
for(Object o: collection)
Basically, objects is an array of objects or primitive, or an Iterable of objects.
Java will iterate over the array or Iterable, set o to the object/value retrieved, and process the block. It allows for quick iteration without dealing with handling your own iterators/
I've an array of objects in Java. Say these objects Obj contain a variable var, and I have several Obj stored in an array Array[].
I'd like to compare the var between two adjacent Obj but I don't know how, nor can I find any info online (which makes me think i'm working my question wrong or it's not doable or something)
Edit:
I'm currently attempting the rather roundabout method of assigning the array objects in question to new temporary objects and just doing the comparison with those:
Obj o1 = o[i];
Obj o2 = o[i+1];
if (o1.var > o2.var)
//etc
But surely there is something better.
If you have an array of objects, you can do your comparison without creating the temporary references:
MyObject[] arr = //populated somehow
for (int index = 0; index < arr.length - 1; index++) {
if (arr[index].var > arr[index + 1].var) {
//your logic
}
}
You might also want to take a look at the Comparable interface as a means of encapsulating the comparison of the objects based on a particular field. Using this interface would allow you to take advantage of its support in the Collections API.
Based on your edit, it would be fine to say
if (o[i].var > o[i+1].var) { ... }
assuming that o was of type Obj[].
I'm curious, though: are you trying to sort the array? If so, you can use Arrays.sort() (If not, it's a good method to know about anyway.)
I may not be understanding your question correctly, but the following is perfectly valid:
if (o[i].var > o[i+1].var ) { // ...etc... }
Beware of when you hit the end of the array! That is, if you are looping through all of the elements and i is the last one, then o[i+1] will give you an Array Index Out of Bounds error!
Just use them directly without the reference i.e. substitute the array lookup into where you are doing the comparison.
if (o[i].var > o[i+1].var) {
// etc
}
Or in a loop, doing every one programmatically:
for (int i=0; i<o.length-1; i++) {
if (o[i].var > o[i + 1].var) {
// etc
}
}
What is stored in 10th location of array
say
int[] array=new int[10];
Say we have values stored from array[0] to array[9], if I were to print elements without using
array.length()
or for (int a: array)
How do I proceed?
My basic question is how will JVM determine end of array, is it when a null is encountered parsing array or when a garbage value is encountered? what is inbuilt code of array.length() function?
What is stored in 10th location of array say
...
my basic question is how will JVM determine end of array, is it when a null is encountered parsing array or when a garbage value is encountered? what is inbuilt code of array.length() function?
Welcome C/C++ programmer :-)
Java uses a different paradigm than C/C++ for arrays. C/C++ uses the terminator/sentinel a.k.a. "garbage") value like NULL to indicate the end of the array. In Java, arrays are more like objects with a special "instance variable"-like variable length that indicates how many slots there are in the array. This special "instance variable" is set at the array's creation and is read-only. Its accessible by saying array.length.
Java expects the code to know when to stop at the end of the array by making sure they don't specify an index greater than length - 1. However, the JVM checks every access to the array for security reasons just in case. If the JVM finds an array index that is less than 0 or greater than length - 1, then the JVM throws an IndexOutOfBoundsException.
What is stored in 10th location of array
Since we can always check the length, there is no need for a marker at the end of the array in Java. There isn't anything special after the last item in the array (it likely will be some other variable's memory).
if I were to print elements without using array.length()
for(int a: array) {
// code of loop body here
}
This code is magically transformed by the compiler to:
for (int i = 0; i < array.length; i++) {
int a = array[i];
// code of loop body here
}
However, the i index variable isn't accessible to the user's code. This code still uses array.length implicitly.
Arrays are objects with a length field. While looping, Java loads the length field and compares the iterator against it.
See 10.7 Array Members in the JLS
Internally, the JVM can track the length of an array however it sees fit. There's actually a bytecode instruction called arraylength that the Java compiler emits whenever you try to get the length of an array, indicating that it's up to the JVM to determine the best way to track the length of an array.
Most implementations probably store arrays as a block of memory whose first entry is the length of the array and whose remaining elements are the actual array values. This allows the implementation to query the length of the array, along with any value in the array, in O(1). If the implementation wanted to, though, it could store the elements followed by a sentinel value (as you've suggested), but I don't believe that any implementations do this because the cost of looking up the length would be linear in the size of the array.
As for how the foreach loop works, the compiler translates that code into something like this:
for (int i = 0; i < arr.length; ++i) {
T arrayElem = arr[i];
/* ... do work here ... */
}
And finally, with regards as to what the 10th element of a 10-element array is, there's no guarantee that there's even an object at that location. The JVM could easily allocate space for the array in a way where there is no tenth element. Since you can't ever actually get this value in Java (it would throw an exception if you tried), there's no requirement that the JVM even have something meaningful there.
Hope this helps!
Define what a "garbage value" is. (Hint: since everything is binary, there is no such thing unless you use a sentinel value, and that's just bad practice).
The length of the array is stored inside the Array instance as a member variable. It's nothing complex.
In a comment on another, the OP writes:
I agree array.length is the conventional method, I was looking for any other option if available.
There is no other reasonable implementation option open to the JVM implementer ... on any mainstream hardware architecture.
In particular, the sentinel approach ONLY detects the case where an application fetches an array element one index beyond the end.
If it fetches 2 or more indexes beyond, then it misses the sentinel and proceeds to access memory whose contents are unknown.
If it stores, then the sentinel is not consulted.
If it needs to directly access the array size as part of the application algorithm, searching for a sentinel is a very inefficient way of doing it. (Not to mention unreliable; e.g. if null is a valid array element.)
Sentinels don't work for (most) primitive arrays because there is no value that can be used as a sentinel. (The idea of a primitive array holding a null is nonsensical from the JLS perspective, since null is not type compatible with any Java primitive type.)
The garbage collector needs an array length in all cases.
In short, the length has to be stored in the array to deal with the other cases. Storing a sentinel as well means you are wasting space storing redundant information, and CPU cycles creating the sentinel and copying it (in the GC).
Okay, here I go :-)
Ways to deal with "arrays" in C
In C there are numerous ways to deal with array. For the remainder I will talk about string* (and use the variable strings which has a type of string*). This is because t[] "effectively decomposes" into t* and char* is the type of a "C string". Thus string* represents a pointer to "C string". This glosses over a number of pedantic issues in C w.r.t. "arrays" and "pointers". (Remember: just because a pointer can be accessed as p[i] doesn't make the type an array in C parlance.)
Now, strings (of type string*) has no way to know it's size -- it only represents a pointer to some string, or NULL perhaps. Now, let's look at some of the ways we can "know" the size:
Use a sentinel value. In this I am assuming the use NULL as the sentinel value (or it might be -1 for an "array" of integers, etc.). Remember that C has no such requirement that arrays have a sentinel value so this approach, like the following two, is just convention.
string* p;
for (p = strings; p != NULL; p++) {
doStuff(*p);
}
Track the array size externally.
void display(int count, string* strings) {
for (int i = 0; i < count; i++) {
doStuff(strings[i]);
}
}
Bundle the "array" and the length together.
struct mystrarray_t {
int size;
string* strings;
}
void display(struct mystrarray_t arr) {
for (int i = 0; i < arr.size i++) {
doStuff(arr.strings[i]);
}
}
Java uses this last approach.
Every array object in Java has a fixed sized which can be accessed as arr.length. There is special byte-code magic to make this work (arrays are very magical in Java), but at the language level this is exposed as just a read-only integer field that never changes (remember, each array object has a fixed size). Compilers and the JVM/JIT can take advantage of this fact to optimize the loop.
Unlike C, Java guarantees that trying to access an index out of bounds will result in an Exception (for performance reasons, even if it were not exposed, this would require the JVM kept track of the length of each array). In C this is just undefined behavior. For instance, if the sentinel value wasn't within the object (read "the desired accessibly memory") then example #1 would have lead to a buffer-overflow.
However, there is nothing to prevent one from using sentinel values in Java. Unlike the C form with a sentinel value, this is also safe from IndexOutOfBoundExceptions (IOOB) because the length-guard is the ultimate limit. The sentinel is just a break-early.
// So we can add up to 2 extra names later
String names[] = { "Fred", "Barney", null, null };
// This uses a sentinel *and* is free of an over-run or IOB Exception
for (String n : names) {
if (n == null) {
break;
}
doStuff(n);
}
Or possibly allowing an IOOB Exception because we do something silly like ignore the fact that arrays know their length: (See comments wrt "performance").
// -- THERE IS NO EFFECTIVE PERFORMANCE GAIN --
// Can ONLY add 1 more name since sentinel now required to
// cleanly detect termination condition.
// Unlike C the behavior is still well-defined, just ill-behaving.
String names[] = { "Fred", "Barney", null, null };
for (int i = 0;; i++) {
String n = strings[i];
if (n == null) {
break;
}
doStuff(n);
}
On the other hand, I would discourage the use of such primitive code -- better to just use a suitable data-type such as a List in almost all cases.
Happy coding.
In terms of how you'd print all the elements in the array without using either a for each loop or the length field, well in all honesty you just wouldn't. You could potentially just have a for loop like the following:
try {
for(int i=0 ; ; i++) {
System.out.println(arr[i]);
}
}
catch(IndexOutOfBoundsException ex) {}
But that's an awful way to do things!
how will you print elements without using array.length or foreach loop
You could of course loop through the array without bounds checking and then catch (and swallow) the ArrayIndexOutOfBoundsException in the end:
try {
int i = 0;
while (true) {
System.out.println(arr[i++]);
}
catch (ArrayIndexOutOfBoundsException e) {
// so we are past the last array element...
}
This technically works, but it is bad practice. You should not use exceptions for flow control.
All array access outside the interval [0, 9] gives an ArrayIndexOutOfBoundsException, not only position 10. So, conceptually you could say that your whole memory (reaching with indexes from Integer.MIN_VALUE to Integer.MAX_VALUE) is filled with sentinel values, apart from the space of the array itself, and when reading or writing to a position filled with a sentinel, you get your exception. (And each array has its own whole memory to spend).
Of course, in reality no one has a whole memory for each array to spend, so the VM implements the array accesses a bit smarter. You can imagine something like this:
class Array<X> {
private final int length;
private final Class<X> componentType;
/**
* invoked on new X[len] .
*/
public Array<X>(int len, Class<X> type) {
if(len < 0) {
throw new NegativeArraySizeException("too small: " + len);
}
this.componentType = type;
this.len = len;
// TODO: allocate the memory
// initialize elements:
for (int i = 0; i < len; i++) {
setElement(i, null);
}
}
/**
* invoked on a.length
*/
public int length() {
return length;
}
/**
* invoked on a[i]
*/
public X getElement(int index) {
if(index < 0 || length <= index)
throw new ArrayIndexOutOfBoundsException("out of bounds: " + index);
// TODO: do the real memory access
return ...;
}
/**
* invoked on a[i] = x
*/
public X setElement(int index, X value) {
if(index < 0 || length <= index) {
throw new ArrayIndexOutOfBoundsException("out of bounds: " + index);
}
if(!componentType.isInstance(value)) {
throw new ArrayStoreException("value " + value + " is of type " +
value.getClass().getName() + ", but should be of type "
+ componentType.getName() + "!");
}
// TODO: do the real memory access
return value;
}
}
Of course, for primitive values the component type check is a bit simpler, since already the compiler (and then the VM bytecode verifier) checks that there are the right types, sometimes doing a type conversion, too. (And the initialization would be with the default value of the type, not null.)
If there is a method call MyClass.returnArray() and I iterate over the array using the for-each construct (also called the "enhanced for" loop):
for (ArrayElement e : MyClass.returnArray()) {
//do something
}
will then the returnArray() method be called for every iteration?
No, it won't. The result of the first call will be stored in the compiled code in a temporary variable.
From Effective Java 2nd. Ed., Item 46:
Note that there is no performance penalty for using
the for-each loop, even for arrays. In fact, it may offer a slight performance advantage
over an ordinary for loop in some circumstances, as it computes the limit of
the array index only once.
From the java language spec:
EnhancedForStatement:
for ( VariableModifiersopt Type Identifier: Expression) Statement
and later on:
T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
VariableModifiersopt Type Identifier = a[i];
Statement
}
This is (in pseudo code) the equivalent of the advanced for loop for arrays. And it is made clear, that the Expression is evaluated once and the resulting array is assigned to T[] a.
So it's perfectly safe to use even complex expressions in the advanced for loop statement.
No.
The for loop is just syntactic sugar. It behaves differently depending on whether or not it is applied to an Array argument or an object implementing the Iterable interface.
For Iterable objects, the loop expands to something like this:
Iterator<ArrayElement> iter = iterableObject.iterator();
while (iter.hasNext()) {
ArrayElement e = iter.next();
// do smth
}
What your example code is actually doing is something like this:
Object[] temp = Method.returnArray();
for ( int i = 0; i < temp.length; i++ ) {
ArrayElement e = (ArrayElement) temp[i];
// do smth
}
No, it will be called once. It's not like the termination condition of a standard for loop, which gets evaluated on every iteration.