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
}
}
Related
This question already has answers here:
What is the Cost of Calling array.length
(8 answers)
Java native array lengths
(6 answers)
Closed 9 years ago.
Let's say I create an array of ints with length 10, i.e.
int[] array = new int[10];
At some point in my code, I want to compare the value of an int variable, let's call it var, with the length of the array.
I would like to know if this piece of code:
if(var == array.length) { // stuff }
and this piece of code:
if(var == 10) { // stuff }
which do exactly the same thing, have also the same performance.
In other words, I would like to know the internal mechanics that the JVM (?) uses to find the length of the array (I don't say "to return" since length is a field, not a method). Does it make use of iteration? Because if it does, then the 2nd piece of code would be faster than the 1st one.
EDIT: Similar question regarding array.length cost (even though focusing more to its use in for loops):
What is the Cost of Calling array.length
.length is a property, so it would not do iteration for sure. Still, the value of the property is, naturally, fetched at runtime, meaning that the second solution will be a little bit faster (as this is comparison with constant).
Still the first implementation is far more preferable:
This makes your code quite more maintainable
You can alter the length of the array only at one place
You will never feel the performance difference unless you pass through this if litterally millions of times in a second.
EDIT By the way you can yourself tell this is a property - there are no braces after the call. I at least do not know of a way in java to make property access do additional computation, but just retrieving its value.
.length is a property of the array, not a function. Thus, the result would be available immediately, with no iteration necessary.
From the Java Doc
The members of an array type are all of the following:
The public final field length, which contains the number of components
of the array. length may be positive or zero.
length is an final field of array, so no iterations are required while writing following code.
if(var == array.length) { // stuff }
And it is good coding practice indeed.
The length property of an array is extracted in constant (O(1)) time - there is no iteration needed. It's also good practice to use this.
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
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?
I know it is a primitive question but I want to learn the smartest way.
I want to loop over the ArrayList<Integer> intList and it can be null. I have 2 ways of doing it
if(intList != null) {
for(int i = 0; i < intList.size(); i++){
System.out.println(intList.get(i));
}
}
and
for (int i = 0; intList != null && i < intList.size(); i++){
System.out.println(intList.get(i));
}
First way seems more pretty to me. What do you think? What are your implementations in that situation?
Excuse me, if it is duplicate question but I can't find one
Thanks
In this case I would choose the first implementation as well because its intent is clearer.
Generally, I would try to avoid a List (or any other Collection object, really) being null. When evaluating a List (which is suddenly and unexpectedly null) you most probably want to abort before any processing takes place so either case of looping over the collection would not occur.
We have one development rule in our company:
If a function is written that returns a list or an array, never return null! Return an empty list or an empty Array in the case where there are no elements to return.
This can be done with minimal overhead, like here:
public List<String> getNames() {
if( !loaded ) {
return Collections.emptyList();
}
...
}
If applied properly, you don't have to check for null-lists. We don't have to.
EDIT: Oh, and to come back to your question at hand: Use the forst variant, it is much clearer, and faster, because the null check only have to be done once (it might be that the compiler factors it out anyway, but in variant 1 you can be sure).
I prefer the first one, for the complete code segment will most likely to be:
if(intList != null) {
for(int i = 0; i < intList.size(); i++){
System.out.println(intList.get(i));
}
}
else {
//Do something here.
}
i preffer the first one as mostly i use the first process
To me the first option is clearer and easier to read and understand.
According to me first option should be preferred for its readability is better than second one, while the second one saves one extra line of code for you.
End of the day both are going to do same thing so its up to you, which code you want to use. I would suggest to stick to first as it is more developer friendly because of readability.
The first form is more readable - the intent is much clearer.
The first form may also be faster, since the second form says to test that intList is not null each time you go around the loop. (The JIT compiler may optimize away the unnecessary tests ... but why rely on this.)
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.