Enhanced for loop - java

I often come across cases where I want to use an enchanced for-loop for some Collection or array that I get from some object.
e.g.
items = basket.getItems();
for (int item : items) {
// Do something
}
Another way to do that is:
for (int item : basket.getItems()) {
// Do something
}
The second one is more compact and improves readability in my opinion, especially when the item variable won't be used anywhere else.
I would like to know whether the getter in the for statement has any impact in performance. Will it be optimized to something similar to the 1st one? Or will it access the getter every time? Of course the getItems() might do something quite slow (e.g. network access, etc)
Question is similar to some others, but is referring to the getter of the collection/array itself and not the size of it. However, it may be the same case in the end.

The getItems() method will be called only once in both cases. There is no difference between the two, apart from one using an extra local variable which you could use somewhere else.
As you can read in JLS 14.14.2, the enhanced for loop is translated roughly to this traditional for loop:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
TargetType Identifier = (TargetType) #i.next();
Statement
}
#i is an automatically generated identifier that is distinct from any other identifiers (automatically generated or otherwise) that are in scope (§6.3) at the point where the enhanced for statement occurs.
From here it's clear that Expression is evaluted only once.

As you can see on the following code sample, on the enhanced for, the initialization of the collection on which to iterate is done only once. So, the second choice is more compact, and does not impact performance.
package test;
public class Main {
static class Basket {
int[] items = { 1, 2, 3 };
public int[] getItems() {
System.out.println("in getItems()");
return items;
}
}
public static void main(String[] args) {
Basket basket = new Basket();
for (int item : basket.getItems()) {
System.out.println(item);
}
}
}

Yes second one improves readability of code.
if you are getting the objects from network and then iterating over it in a for loop then I think yes it has performance impact because you are making network access every time and that is inefficient also as for a small/single object doing network access is not recommended. instead of that get it once from network access store it locally and iterate over it
thus 1st option is performance optimized in network access case
if your object is local then any method will do. there wont be much performance difference.

I don't think it will call getter every time. If it does it will get new list every time and Loop wont break. You can test this by putting simple Sysout inside getter method. Performance will be same in these two cases.

Related

Which approach is better comparing a value in method check or checking if it exists in an array?

Consider I have a scenario where certain awesome tasks need to be done when it satisfies the condition.
public class Check101 {
public static boolean validColor(String color) {
return color.equals("RED")
|| color.equals("BLUE")
|| color.equals("GREEN");
}
public static List<String> validColorList= new ArrayList<String>(Arrays.asList("RED","GREEN","BLUE"));
public static void main(String[] args) {
String color = "RED";
if (validColor(color)) {
//do awesome work
}
if(validColorList.contains(color)){
//do awesome work
}
}
}
Right now it seems fine as it has only primary colors,
What if the valid color increases to let's say (i)100 and (ii)16 million color.
Then which is the best approach to go with?
Please note I was in a constraint not to use Set/HashMap or O(1) searchable containers and was asked to answer this weird scenario only.
When you use a List, there is no reason to copy the list produced via Arrays.asList("RED","GREEN","BLUE") into another ArrayList. You can simply declare it like
public static List<String> validColorList = Arrays.asList("RED","GREEN","BLUE");
When you are not allowed to use a Set, both approaches perform a linear search, which is similarly bad performance-wise. But the list approach is simpler to maintain, as adding another value just requires, well, adding that value (to the initializer list), rather than adding another if statement.
That might scale well up to 100 values whereas even the performance drawback of a linear search might be irrelevant for 100 values, as long as you don’t perform the lookup very often, e.g. in a tight loop.
However, neither approach can be used for 16M colors. It’s not even impractical or having catastrophic performance, it’s just impossible. The maximum code size of a Java method is 65536 bytes, which applies to both, an ordinary method holding if statements or a class initializer constructing a List. Each expression or statement requires several bytes, so both approaches will stop working already at a threshold of a few thousand values. Even if you split the code into multiple methods, the number of string constants you can define within a single class are less than 65535.
To manage a larger number of values, you should embed the name list as a resource into your code and use something like, e.g.
public static final List<String> validColorList;
static {
try {
validColorList = Files.readAllLines(
Paths.get(MyClass.class.getResource("color-list").toURI()));
} catch(IOException|URISyntaxException ex) {
throw new ExceptionInInitializerError(ex);
}
}
But when we are at making such changes, there’s no reason to hesitate regarding the other strongly recommended change:
public static final Set<String> validColorList;
static {
try {
validColorList = new HashSet<>(Files.readAllLines(
Paths.get(SO59045501.class.getResource("color-list").toURI())));
} catch(IOException|URISyntaxException ex) {
throw new ExceptionInInitializerError(ex);
}
}
There is no equivalent for the approach of chaining if statements.
That depends on what you consider "better".
When comparing to a value you have the advantage of direct access, while using the array you have the overhead of iterating the array. So there is a small performance advantage to value comparing approach.
On the other end, using the array is a more generic approach that will be easily enhanced (reading the array from file or pulling it from the web). Moreover, it's more suitable for Dependency Injection (keeping the logic in the class while allowing the values for external source) which is more testable.

Why do we need to avoid mutations while coding? What is a mutation?

Why is the second code (the one with the stream) a better solution than the first?
First :
public static void main(String [] args) {
List<Integer> values = Arrays.asList(1,2,3,4,5,6);
int total = 0;
for(int e : values) {
total += e * 2;
}
Second :
System.out.println(total);
System.out.println(
values.stream()
.map(e-> e*2)
.reduce(0, (c, e)-> c + e));
Mutation is changing an object and is one common side effect in programming languages.
A method that has a functional contract will always return the same value to the same arguments and have no other side effects (like storing file, printing, reading). Thus even if you mutate temporary values inside your function it's still pure from the outside. By putting your first example in a function demonstrates it:
public static int squareSum(const List<Integer> values)
{
int total = 0;
for(int e : values) {
total += e * 2; // mutates a local variable
}
return total;
}
A purely functional method doesn't even update local variables. If you put the second version in a function it would be pure:
public static int squareSum(const List<Integer> values)
{
return values.stream()
.map(e-> e*2)
.reduce(0, (c, e)-> c + e);
}
For a person that knows other languages that has long been preferring a functional style map and reduce with lambda is very natural. Both versions are easy to read and easy to test, which is the most important part.
Java has functional classes. java.lang.String is one of them.
Mutation is changing the state of an object, either the list or some custom object.
Your particular code does not cause a mutation of the list either way, so there's no practical benefit here of using lambdas instead of plain old iteration. And, blame me, but I would use the iteration approach in this case.
Some approaches say that whenever you need to modify an object/collection, you need to return a new object/collection with the modified data instead of changing the original one. This is good for collection for example when you concurrently access a collection and it's being changed from another thread.
Of course this could lead to memory leaks, so there are some algorithms for managing memory and mutability for collection i.e. only the changed nodes are stored in another place in memory.
While Royal Bg is right you're not mutating your data in either case, it's not true that there's no advantage to the second version. The second version can be heavily multithreaded without ambiguity.
Since we're not expecting to iterate the list we can put the operations into a heavily multi-threaded context and solve it on a gpu. In the latter one each data point in the collection is multiplied by 2. Then reduced (which means every element is added together), which can be done by a reduction.
There are a number of potential advantages to the latter code not seen in the former. And while neither code element actually mutates, in the second one we are given the very clear contract that the items cannot mutate while that is happening. So we know that it doesn't matter if we iterate the list forwards, backwards, or apply it multithreaded etc. The implementation details can be filled in later. But, only if we know mutation can't happen and streams simply don't allow them.

Efficiency of method call in for loop condition

I am writing a game engine, in which a set of objects held in a ArrayList are iterated over using a for loop. Obviously, efficiency is rather important, and so I was wondering about the efficiency of the loop.
for (String extension : assetLoader.getSupportedExtensions()) {
// do stuff with the extension here
}
Where getSupportedExtension() returns an ArrayList of Strings. What I'm wondering is if the method is called every time the loop iterates over a new extension. If so, would it be more efficient to do something like:
ArrayList<String> supportedExtensions = ((IAssetLoader<?>) loader).getSupportedExtensions();
for (String extension : supportedExtensions) {
// stuff
}
? Thanks in advance.
By specification, the idiom
for (String extension : assetLoader.getSupportedExtensions()) {
...
}
expands into
for (Iterator<String> it = assetLoader.getSupportedExtensions().iterator(); it.hasNext();)
{
String extension = it.next();
...
}
Therefore the call you ask about occurs only once, at loop init time. It is the iterator object whose methods are being called repeatedly.
However, if you are honestly interested about the performance of your application, then you should make sure you're focusing on the big wins and not small potatoes like this. It is almost impossible to make a getter call stand out as a bottleneck in any piece of code. This goes double for applications running on HotSpot, which will inline that getter call and turn it into a direct field access.
No, the method assetLoader.getSupportedExtensions() is called only once before the first iteration of the loop, and is used to create an Iterator<String> used by the enhanced for loop.
The two snippets will have the same performance.
Direct cost.
Since, as people said before, the following
for (String extension : assetLoader.getSupportedExtensions()) {
//stuff
}
transforms into
for (Iterator<String> it = assetLoader.getSupportedExtensions().iterator(); it.hasNext();) {
String extension = it.next();
//stuf
}
getSupportedExtensions() is called once and both of your code snippets have the same performance cost, but not the best performance possible to go through the List, because of...
Indirect cost
Which is the cost of instantiation and utilization of new short-living object + cost of method next(). Method iterator() prepares an instance of Iterator. So, it is need to spend time to instantiate the object and then (when that object becomes unreachable) to GC it. The total indirect cost isn't so much (about 10 instructions to allocate memory for new object + a few instructions of constructor + about 5 lines of ArrayList.Itr.next() + removing of the object from Eden on minor GC), but I personally prefer indexing (or even plain arrays):
ArrayList<String> supportedExtensions = ((IAssetLoader<?>) loader).getSupportedExtensions();
for (int i = 0; i < supportedExtensions.size(); i++) {
String extension = supportedExtensions.get(i);
// stuff
}
over iterating when I have to iterate through the list frequently in the main path of my application. Some other examples of standard java code with hidden cost are some String methods (substring(), trim() etc.), NIO Selectors, boxing/unboxing of primitives to store them in Collections etc.

List object reference changed during Java loop

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;
}

for(Something s : something.getList())

I have quick question
Does it matter if I use clause this way :
for(Object obj : something.b.c.d.getList(){
...
}
or this
List list = something.b.c.d.getList();
for(Object obj : list){
...
}
I'm wondering if one is faster than other
The main difference is stylistic. The semantics are pretty much the same. The only significant semantic difference is that, in the second example, the list reference is named and can be accessed both inside and after the loop:
List list = something.b.c.d.getList();
for(Object obj : list){
if (list.contains(...)) { // inefficient, used purely as an illustration
...
}
}
int n = list.size();
The above cannot be achieved in the first example without evaluating something.b.c.d.getList() again.
If you are concerned that the first example repeatedly evaluates something.b.c.d.getList(), that's certainly not the case. Both of your examples evaluate the expression exactly once.
There's likely no difference in performance, but performance overall would depend on how expensive it is to access those fields (i.e. lazy loading from a framework). Accessing the fields would only happen once, regardless of whichever style you chose to use for this loop.
Both approaches are acceptable if both items are something that can be used in the enhanced-for statement.
I wouldn't concern myself with optimizations like this unless a profiler designated this particular area of your code as a trouble spot.

Categories