Array iteration with static final limits - java

I have an array:
final int[] exampleArray = new int[ID_DATA_ARRAY_SIZE];
And I can iterate that array several ways, for example:
Way 1:
for (int i = 0; i < exampleArray.length; i++) {
// code where I use 'i' index
}
Way 2:
for (int i = 0; i < ID_DATA_ARRAY_SIZE; i++) {
// code where I use 'i' index
}
Which way is better? Are there any other better ways to do it?

If you don't need i for anything else than extracting the element, then the enhanced for loop looks a bit nicer:
for(int element : exampleArray) {
//code that uses element
}
If you are using i for both accessing the array, and something else, then I would argue Way 1 is best:
for (int i = 0; i < exampleArray.length; i++) {
// code where I use 'i' index
}
The reason is that the next time someone looks at a code, the person will immediately see that you are iterating to the length of the array. If you go for way 2 (using a constant), the reader might wonder if that constant really is the length of your array.

Tackling both performance, and code readability, way 2 is better.
Rated by performance, by using exampleArray.length you are calling upon a "member" variable which requires additional java bytecode to request when compared to calling a "local" variable. But, the difference in performance is extremely minuscule and you would never notice it unless you were making an extreme amount of calculations.
Rated by readability, ID_DATA_ARRAY_SIZE lays out your intent for whomever is reading, which is more important than it may seem. Yet, too many programmers lay out nonsensical or ambiguous variable names, and it makes reading their code lacking in naturalness. Naming variables and functions in a way that makes sense to our minds in an organic way makes the code much simpler to deal with for yourself in the future, and anyone else, making it a good practice.

The fundamental difference in the two approaches, I see is as below:
In Way 1: you use the constant exampleArray.length in the loop condition
In Way 2: you use the constant ID_DATA_ARRAY_SIZE in the loop condition
Obviously way 2 is superior in terms of performance.
This is because you are accessing a constant rather than access member variable of exampleArray object. This advantage is realized in every iteration of the for loop where the value of length member is accessed.

see it is all about personal taste which way you wanna do but whenever you are working with array better to check null for the array and then do your stuff

Related

Which one is preferable? [duplicate]

This question already has answers here:
Time complexity for java ArrayList
(6 answers)
Closed 6 years ago.
I am getting arraylist.get(i) every time a loop executes more than three times within the loop.
Is it advisable or shall I store it in separate variable then use it again and again? Which one is preferable performance wise?
Setting it to a variable is slightly more efficient. Accesing arrayList.get (I) is O (1) but still costs something eventhough it is really minor and insignificant.
Setting it to a variable is more readable in my opinion.
It's always a good approach to write readable and maintainable code. Since you question is very broad so expect broad answers as well.
List<Integer> integerList = new ArrayList<>();
for (int i=0;i<integerList.size();i++) {
Integer integerValue = integerList.get(i);
// make sure integerValue is not null.
// Thanks #Tom for pointing this out
System.out.println (integerValue);
// Do operations
System.out.println (integerValue);
// Do more operations
System.out.println (integerValue);
}
Now this is one time assignment but you can use it at multiple times. Now, for instance, you have to change the logic of program so that you want to get always i+1, it will be easy for you to change only once, not multiple times.
As others mentioned, getting object one time is slightly more efficient. Of course most of times this won't produce any problems and you can't notice any differences.
Logically because it's an O(1) operation, it shouldn't cause any differences at all, but because it calls a function of an object of type ArrayList , It's less cache friendly and direct memory reference maybe needed. Still the difference is very little.
declaring and assigning a variable once like String myString = arraylist.get(i); will be marginally faster than calling arraylist.get(i) multiple times.
Once you've done this you can call any methods on the myString instance.
I assume that arraylist is of type ArrayList<String>.
you may want to include a null check in your loop as well:
for(int i = 0; i < arraylist.size(); i++){
String myString = arraylist.get(i);
if(myString != null){
//any calls to methods on myString
}
}

i++ or i-- in a for loop? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
While writing a for loop where both start and end conditions are known, which way is better? Let's say I have to iterate a loop for addition of an array elements of size 5. In this case which one of the following would be more efficient as far as execution time is concerned? Which one will give better performance?
for (i = 0; i < 5; i++)
{
/* logic */
}
OR
for (i = 4; i >= 0; i--)
{
/* logic */
}
Apart from the difficulty in writing i = 5 - 1; that is i = 4;, are there any other considerations?
It's usually recommended to concentrate on making code as clear and as logical as possible, without worrying about micro-optimizations or other factors. In your case, the first one is the better choice, since most programmers are more used to traverse an array in that order.
Both versions will have the same result (given that they're implemented correctly) and will have exactly the same run time.
EDIT: #Zane mentioned in a comment that looping backwards to zero was faster some time ago. It was, the reason for it was that comparing a variable to zero was faster. Given that computers were much much slower those days, such optimizations were encouraged. Those days are indeed over...
There is something wrong in your code.
The first loop is fine but the second while never execute:
it runs for 0 times. It should be
for(i=4;i>=0;i--){}
Besides, if you ask which is better, its your choice, with which one you are comfortable with.
For me, I feel the first one to be more comfortable.
In most cases it wouldn't matter, however there are some situations where non-obvious side-effects might interfere.
Consider a loop:
for(int i = 0; i < strlen(str); i++) {/* do stuff on i-th elem */}.
Here on each iteration the strlen(str) will be reevaluated (unless optimized by compiler) even though it's completely unnecessary; the programmer most likely didn't even consider this.
It might be worth replacing the loop with:
for(int i = strlen(str); i > 0; i--) {/* do stuff on i-th elem */}.
Here length of the string will be evaluated only once.
Of course, in the first loop the problem can be avoided as well by using additional variable to hold the length of the string but it's just an unnecessary noise, not related to the program logic.
The most obvious answer is: which one has the semantics you want? They
visit the objects in a different order.
As a general rule, if there are no other considerations, people expect
ascending order, and this is what you should use when visiting objects.
In C++, it is far more idiomatic to use iterators for this. Normal
iterators visit in ascending order, reverse iterators in descending. If
you don't explicitly need descending, you should use normal iterators.
This is what people expect, and when you do use reverse iterators, the
first thing a reader will ask is why. Also, I haven't measured, but it
wouldn't surprise me if normal iterators were faster than reverse
iterators. In Java, iterators are also idiomatic, and you don't have
reverse iterators.
If I do need descending order when visiting, I'll use a while loop (if I
don't have reverse iterators, which do it for me); I find something
like:
int index = numberOfElements;
while ( index != 0 ) {
-- index;
// ...
}
far more readable (and easier to get right) than any of the
alternatives.
If you're not visiting objects, but just counting, descending order
seems more natural to me: the control variable contains the number of
times left. And since the count is never used as an index, there's no
problem with the fact that it would be one off as an index, and you can
use a traditional for.
for ( int count = numberOfTimes; count != 0; -- count ) {
// ...
}
But it's really a question of style; I've seen a lot of ascending loops
for this as well.
The incremental for loop or decremented for loop is opted based on the way you want to use the counter variable or how good it looks
if you are accessing some array in ascending order, decremented for loop will be used
for (i = 0; i < 5; i++)
{
arr[i];
}
if you are accessing some array or list in descending order, incremental for loop is used
for (i = 5; i > 0 ; i--)
{
arr[i-1];
}
if the counter number has no significance for the value that is accessed, then readability of code is looked on. And incremental for loop looks more eye pleasing.
I would say the loop with i++ is easier to understand. Also, going backwards can make a suboptimal use of the processor cache, but usually compilers/ virtual machines are smarter than that.
I believe most programmers would be able to understand your code more quickly using the first method (i++). Unless you have the need to process an array in reverse I would stick with your first method. As for performance, I believe there would be little or no benefit to either solution.
Also you may want to consider using the for..each (enhanced for) syntax, which is quite tidier.
int[] x = {1,2,3,4,5};
for(int y: x){
System.out.println(y);
}

Simple loop performance issue

Say I have a simple PHP loop like this one
// Bad example
$array = array('apple','banana','cucumber');
for ($i = 1; $i < count($array); $i++) {
echo $array[$i];
}
I know this is a bad practice. It's better not using count() inside a loop.
// Nice example
$array = array('apple','banana','cucumber');
$limit = count($array);
for ($i = 1; $i < $limit; $i++) {
// do something...
}
In Java, I would do it this way
// Bad example?
String[] array = {"apple","banana","cucumber"};
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
Question: Isn't this above a bad practice too? Or it is just the same as the example below?
// Nice example?
String[] array = {"apple","banana","cucumber"};
int limit = array.length;
for(int i = 0; i < limit; i++){
System.out.println(array[i]);
}
Any decent compiler/interpreter should automatically optimise the first example to match the second (semantically speaking anyway, if not exactly literally), and probably the third to match the fourth. It's known as a loop invariant optimisation, where the compiler recognises that an entity (variable, expression, etc) does not vary within the loop (i.e. is invariant) and removes it to outside the loop (loosely speaking).
It's not bad practice at all anymore, if it ever was.
The "bad" examples you use are not equivalent, and thus are not comparable - even if they seem so on the surface. Using this description:
for (initialization; termination; increment) {
statement(s)
}
(which is descriptive of both PHP and java loops), the initialization statement is executed once, at the start of the loop. The termination statement and the increment are executed for each iteration of the loop.
The reason it is bad practice to use PHP's count in the termination statement is that, for each iteration, the count function call occurs. In your Java example, array.length is not a function call but a reference to a public member. Therefore, the termination statements used in your examples are not equivalent behavior. We expect a function call to be more costly than a property reference.
It is bad practice to place a function call (or call a property that masks a function) in the termination statement of a for loop in any language which has the described loop mechanics. That's what makes the PHP example "bad", and it would be equally bad if you used a count-type function in Java for loop's termination statement. The real question, then, is whether Java's Array.length does indeed mask a function call - the answer to that is "no" (see the potential duplicate question, and/or check out http://leepoint.net/notes-java/data/arrays/arrays.html)
The main difference is that count() is a function whereas array.length is a property and therefore not different from a limit variable.
They are not the same, in the Java "nice example" you are not calculating the length of the array every time. Instead, you are storing that in the limit variable and using that to stop the calculation instead of the result of calling the length function on the array every iteration through the for loop.
EDIT: Both of the things that you thought were "bad practice" are bad practice and the "nice examples" are the more efficient ways (at least in theory). But it is true that in implementation there will not be any noticeable difference.
In java this doesn't matter an array has this attribute as a constant (public final int).
The difference is in java arrays have a fixed size and can not grow so there would be no need to count the elements every time to access length.

How do you (get around) dynamically naming variables?

I'm not sure if I'm using the right nomenclature, so I'll try to make my question as specific as possible. That said, I imagine this problem comes up all the time, and there are probably several different ways to deal with it.
Let's say I have an array (vector) called main of 1000 random years between 1980 and 2000 and that I want to make 20 separate arrays (vectors) out of it. These arrays would be named array1980, array1981, etc., would also have length 1000 but would contain 1s where the index in the name was equal to the corresponding element in main and 0s elsewhere. In other words:
for(int i=0; i<1000; i++){
if(main[i]==1980){
array1980[i]=1;
} else {
array1980[i]=0;
}
Of course, I don't want to have to write twenty of these, so it'd be good if I could create new variable names inside a loop. The problem is that you can't generally assign variable names to expressions with operators, e.g.,
String("array"+ j)=... # returns an error
I'm currently using Matlab the most, but I can also do a little in Java, c++ and python, and I'm trying to get an idea for how people go about solving this problem in general. Ideally, I'd like to be able to manipulate the individual variables (or sub-arrays) in some way that the year remains in the variable name (or array index) to reduce the chance for error and to make things easier to deal with in general.
I'd appreciate any help.
boolean main[][] = new boolean[1000][20];
for (int i=0; i < 1000; i++) {
array[i][main[i]-1980] = true;
}
In many cases a map will be a good solution, but here you could use a 2-dim array of booleans, since the size is known before (0-20) and continuous, and numerable.
Some languages will initialize an array of booleans to false for every element, so you would just need to set the values to true, to which main[i] points.
since main[i] returns numbers from 1980 to 2000, 1980-main[i] will return 1980-1980=0 to 2000-1980=20. To find your values, you have to add 1980 to the second index, of course.
The general solution to this is to not create variables with dynamic names, but to instead create a map. Exactly how that's done will vary by language.
For Java, it's worth looking at the map section of the Sun collections tutorial for a start.
Don Roby's answer is correct, but i would like to complete it.
You can use maps for this purpose, and it would look something like this:
Map<Integer,ArrayList<Integer>> yearMap = new HashMap<Integer,ArrayList<Integer>>();
yearMap.put(1980,new ArrayList<Integer>());
for (int i = 0; i < 1000; i++){
yearMap.get(1980).add(0);
}
yearMap.get(1980).set(999,1);
System.out.println(yearMap.get(1980).get(999));
But there is probably a better way to solve the problem that you have. You should not ask how to use X to solve Y, but how to solve Y.
So, what is it, that you are trying to solve?

Array access optimization

I have a 10x10 array in Java, some of the items in array which are not used, and I need to traverse through all elements as part of a method. What Would be better to do :
Go through all elements with 2 for loops and check for the nulltype to avoid errors, e.g.
for(int y=0;y<10;y++){
for(int x=0;x<10;x++){
if(array[x][y]!=null)
//perform task here
}
}
Or would it be better to keep a list of all the used addresses... Say an arraylist of points?
Something different I haven't mentioned.
I look forward to any answers :)
Any solution you try needs to be tested in controlled conditions resembling as much as possible the production conditions. Because of the nature of Java, you need to exercise your code a bit to get reliable performance stats, but I'm sure you know that already.
This said, there are several things you may try, which I've used to optimize my Java code with success (but not on Android JVM)
for(int y=0;y<10;y++){
for(int x=0;x<10;x++){
if(array[x][y]!=null)
//perform task here
}
}
should in any case be reworked into
for(int x=0;x<10;x++){
for(int y=0;y<10;y++){
if(array[x][y]!=null)
//perform task here
}
}
Often you will get performance improvement from caching the row reference. Let as assume the array is of the type Foo[][]:
for(int x=0;x<10;x++){
final Foo[] row = array[x];
for(int y=0;y<10;y++){
if(row[y]!=null)
//perform task here
}
}
Using final with variables was supposed to help the JVM optimize the code, but I think that modern JIT Java compilers can in many cases figure out on their own whether the variable is changed in the code or not. On the other hand, sometimes this may be more efficient, although takes us definitely into the realm of microoptimizations:
Foo[] row;
for(int x=0;x<10;x++){
row = array[x];
for(int y=0;y<10;y++){
if(row[y]!=null)
//perform task here
}
}
If you don't need to know the element's indices in order to perform the task on it, you can write this as
for(final Foo[] row: array){
for(final Foo elem: row
if(elem!=null)
//perform task here
}
}
Another thing you may try is to flatten the array and store the elements in Foo[] array, ensuring maximum locality of reference. You have no inner loop to worry about, but you need to do some index arithmetic when referencing particular array elements (as opposed to looping over the whole array). Depending on how often you do it, it may or not be beneficial.
Since most of the elements will be not-null, keeping them as a sparse array is not beneficial for you, as you lose locality of reference.
Another problem is the null test. The null test itself doesn't cost much, but the conditional statement following it does, as you get a branch in the code and lose time on wrong branch predictions. What you can do is to use a "null object", on which the task will be possible to perform but will amount to a non-op or something equally benign. Depending on the task you want to perform, it may or may not work for you.
Hope this helps.
You're better off using a List than an array, especially since you may not use the whole set of data. This has several advantages.
You're not checking for nulls and may not accidentally try to use a null object.
More memory efficient in that you're not allocating memory which may not be used.
For a hundred elements, it's probably not worth using any of the classic sparse array
implementations. However, you don't say how sparse your array is, so profile it and see how much time you spend skipping null items compared to whatever processing you're doing.
( As Tom Hawtin - tackline mentions ) you should, when using an array of arrays, try to loop over members of each array rather than than looping over the same index of different arrays. Not all algorithms allow you to do that though.
for ( int x = 0; x < 10; ++x ) {
for ( int y = 0; y < 10; ++y ) {
if ( array[x][y] != null )
//perform task here
}
}
or
for ( Foo[] row : array ) {
for ( Foo item : row ) {
if ( item != null )
//perform task here
}
}
You may also find it better to use a null object rather than testing for null, depending what the complexity of the operation you're performing is. Don't use the polymorphic version of the pattern - a polymorphic dispatch will cost at least as much as a test and branch - but if you were summing properties having an object with a zero is probably faster on many CPUs.
double sum = 0;
for ( Foo[] row : array ) {
for ( Foo item : row ) {
sum += item.value();
}
}
As to what applies to android, I'm not sure; again you need to test and profile for any optimisation.
Holding an ArrayList of points would be "over engineering" the problem. You have a multi-dimensional array; the best way to iterate over it is with two nested for loops. Unless you can change the representation of the data, that's roughly as efficient as it gets.
Just make sure you go in row order, not column order.
Depends on how sparse/dense your matrix is.
If it is sparse, you better store a list of points, if it is dense, go with the 2D array. If in between, you can have a hybrid solution storing a list of sub-matrices.
This implementation detail should be hidden within a class anyway, so your code can also anytime convert between any of these representations.
I would discourage you from settling on any of these solutions without profiling with your real application.
I agree an array with a null test is the best approach unless you expect sparsely populated arrays.
Reasons for this:
1- More memory efficient for dense arrays (a list needs to store the index)
2- More computationally efficient for dense arrays (You need only compare the value you just retrieved to NULL, instead of having to also get the index from memory).
Also, a small suggestion, but in Java especially you are often better off faking a multi dimensional array with a 1D array where possible (square/rectangluar arrays in 2D). Bounds checking only happens once per iteration, instead of twice. Not sure if this still applies in the android VMs, but it has traditionally been an issue. Regardless, you can ignore it if the loop is not a bottleneck.

Categories