public void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
}
public void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
According to Android documentation, in above code, zero is slower. But I don't understand why ? well I haven't learn that much deep but as I know length is a field not method. So when loop retrieves its value, how its different from retrieving from local variable ? and array length is always fixed once initialized. What am I missing ?
Well I guess this is because at zero, he always needs to retrieve the information from mArray and in one, he has it accessible. This means, zero needs two "methods":
Access mArray
Access mArray.length
But one only needs one "methods":
Access len
In the first example, the JVM needs to first fetch the reference to the array and then access its length field.
In the second example, it only accesses one local variable.
On desktop JVMs this is generally optimised and the two methods are equivalent but it seems that Android's JVM does not do it... yet...
It is a matter of scope. Accessing an instance variable is slower than a method variable because it is not stored in the same memory places. (because method variables are likely to be accessed more often).
Same goes for len, but with an extra optimization. len cannot be changed from outside the method, and the compiler can see that it will never change. Therefore, its value is more predictable and the loop can be further optimized.
public void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
}
Here if you look at the for loop array length is calculated for every iteration, that degrades
the performance.
public void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
In this case the length is calculated before for loop and then used in the loop.
Related
1. Suppose following situations.
First:
int x;
for (int i = 0; i < MAX; i++){
// some magic with x
System.out.println(x);
}
Second:
for (int i = 0; i < MAX; i++){
int x;
// some magic with x
System.out.println(x);
}
So which piece of code is better and more efficient?
2. Another two situations.
First:
int size = array.length;
for (int i = 0; i < size; i++) {
// do something with array[i]
}
Second:
for (int i = 0; i < array.length; i++) {
// do something with array[i]
}
Is it more efficient to save array length to variable?
length is just a property in the array object, it doesn't take any time in getting the length.
It is the same as reading from a variable it doesn't need to loop over the whole array to get the length.
And the first two are just scopes.
Local - only available within the loop.
Global - available throught.
Assume you want remainders of numbers when divided by 2.
for(int i = 0; i < 10; ++i)
{
int remainder = i % 2;
System.out.println(remainder);
}
And assume calculating the sum of first 10 natural numbers.
int sum = 0;
for(int i = 0; i <= 10; ++i)
{
//declaring sum here doesnt make sense
sum += i;
}
System.out.println(sum);//sum is available here.
PS: you could just the sum of n natural numbers formula.
1. What you should be more concerned with here, is not efficiency, but scope. Generally, you should strive to keep your variables as locally scoped as possible. This means, if you only need x within the loop, you should define it within the loop.
You get a number of benefits with keeping your variables as locally scoped as possible:
Your code will be much more readable to someone else
You won't accidentally assign to, or use the value of a variable you defined further up in your code that is still in scope, thus minimizing errors in your program
Most importantly, the garbage collector will free up any memory used by the variable as soon as it goes out of scope, keeping your program's performance high, and memory usage low.
You can read up more on variable scope and best practices from Josh Bloch's excellent book, "Effective Java" (scope is discussed in items 13 and 45). You might also want to read item 55, which discusses why it is important to optimize judiciously.
2. For the second part of your question, see The Skeet's answer here.
Here's an example:
public static void main(String[] args) {
for(int i=0; i<getSize(); i++) {
System.out.println("i: " + i);
}
}
private static int getSize() {
int size = new Random().nextInt(10);
System.out.println("size: " + size);
return size;
}
This outputs:
size: 2
i: 0
size: 4
i: 1
size: 4
i: 2
size: 8
i: 3
size: 0
Notice how getSize() is called for every iteration of the loop. In your example, calling .length won't make a huge difference, as the JIT runtime will know how to optimize this call. But imagine getSize() was a more complex operation, like counting the number of rows in a database table. Your code will be super slow as every iteration of the loop will call getSize(), resulting in a database roundtrip.
This is when you would be better off evaluating the value before hand. You can do this and still retain minimal scope for size, like this:
public static void main(String[] args) {
for(int size = getSize(), i=0; i<size; i++) {
System.out.println("i: " + i);
}
}
private static int getSize() {
int size = new Random().nextInt(10);
System.out.println("size: " + size);
return size;
}
size: 5
i: 0
i: 1
i: 2
i: 3
i: 4
Notice how getSize() is only called once, and also, the size variable is only available inside the loop and goes out of scope as soon as the loop completes.
So I was trying to write a function for a ragged array; I may have got this entirely wrong, if so please explain why/how I went wrong. It took me ages to get this far and I have a feeling I've alreayd done it wrong.
I tried compiling it because I'm pretty sure currently it will work, however i'm getting the error "variable n may not have been initialized". My code so far is:
static double[][] exampleMatrix()
{
int n;
double[][] a = new double [3][];
a[0] = new double[n-1];
a[1] = new double[n];
a[2] = new double[n-1];
{
for (int i = 0; i < n-1; i++)
{
a[0][i] = 1;
a[2][i] = 1;
}
for (int i = 0; i < n; i++)
{
a[1][i] = - i - 1;
}
return a;
}
}
I'm probably missing something really really obvious, but i'm not sure what it is to initialize n.
EDIT: I have been told to make this work for a value n that is not yet given.. How would I do that? As in, the user is supposed to input the value of n, and be given an array in return.
Basically, my given question is to implement a function exampleMatrix that, given n, produces the array where all values in teh array a[0] is 1, and same for a[2], and then for a[1], be given a range of values from -1 down to -n for a[1][n-1]. This is what I have so far to calculate this, but I am guessing I have gone completely wrong?
You don't set any value to n. How will your program know how big to make the arrays and how many iterations to run in the for loops?
Method variables (unlike fields) cannot rely on the default value (0 in this case). As such n is not anything when it is declared
int n;
You need to state what n is at some point between declaring it and using it, for example.
int n;
n=7;
or
int n=7;
n not known at compile time
You can also pass n as a variable, if n is variable
static double[][] exampleMatrix(int n){
double[][] a = new double [3][];
a[0] = new double[n-1];
a[1] = new double[n];
a[2] = new double[n-1];
{
for (int i = 0; i < n-1; i++)
{
a[0][i] = 1;
a[2][i] = 1;
}
for (int i = 0; i < n; i++)
{
a[1][i] = - i - 1;
}
return a;
}
}
This method would then be used as
double[][] someMatrix= exampleMatrix(5); //<-- 5 is passed into the function and becomes n
Or you can calculate n in whatever way you see fit
Actually the Problem is with local variable
int n;
The scope of local variables is much narrower. Compiler knows when its getting used. Hence, forcing programmer to initialize the variable
You have to initialize it with any default value as int n=0;
I want to complement the above responses.
You have to take care with the static segments, because when a class load its static segments, the class don't assign default value, if you type:
public static int n;
in your class, the value depends on the programmer. this can throw an exception about initialized.
Write a method called fillIntArray that takes two parameters – an integer array and an integer. The method must copy the integer parameter into each element of the integer array. The method does not have a return value.
Below is my current code, the test method applies random array lengths and variables for the integer, but I'm struggling with the concept of inputting data into an array. I understand pulling info but unsure of how to write the code to input it.
Can someone please indicate effective ways of writing this code?
public class Q8 {
void fillIntArray(int [] array, int x) {
for(int i = 0; i < x; ++i) {
array[i] = +x;
}
}
}
That code demonstrates knowledge of how to insert data into an array. But a few hints:
Your loop should go from 0 to array.length, not 0 to x.
It's a good idea to use x in the assignment statement, not +x. This makes the code more clear, and prevents bozos like me from thinking it will make the code not work.
Try following code. You should iterate over the whole array and put value x in each location.
public class Q8 {
void fillIntArray(int [] array, int x) {
for(int i = 0; i < array.length; ++i) {
array[i] = x;
}
}
}
The fasted way:
void fillIntArray(int[] array, int val) {
for (int i = 0, len = array.length; i < len; i++)
array[i] = val;
}
What is the best way to loop through an array when you need the index?
Option 1:
int len = array.length;
for (int i = 0; i < len; ++i) {
array[i] = foo(i);
}
Option 2:
for (int i = 0; i < array.length; i++) {
array[i] = foo(i);
}
Or, does it not matter? Or is there a better way to do it?
Just to point out the differences: In one case, the length of the array is evaluated as part of the test in the loop, although the compiler should normally optimize that.
Secondly, is ++i any different here from i++? I definitely prefer ++i if it is C++ but am not sure for Java.
i++ vs ++i does not matter in this particular case. While C masters will tell you to store array.length in a variable, modern optimizing compilers make that unnecessary in this case as long as the length does not change in the loop. If you're really concerned you can benchmark both, but since .length doesn't actually need to traverse the entire array each time you'll be OK.
Generally those two methods are equivalent. You should note that in
for (int i = 0 ; i < foo() ; i++) {
...
}
the foo() is called once before each iteration (as opposed to only once before the first iteration), so you might want to take this into account for more complicated situations by perhaps doing something like
int n = foo();
for (int i = 0 ; i < n ; i++) {
...
}
which is analogous to your Option 1. So I would say Option 1 is certainly the safer of the two, but most of the time it should not make a significant difference which you use.
As for your second question: ++i first increments your variable and then retrieves it's value, i++ first retrieves the value and then increments. Just try these two pieces of code:
int i = 0;
System.out.println(++i);
------------------------
int i = 0;
System.out.println(i++);
The first prints 1 but the second prints 0. Of course when ++i and i++ are alone it makes no difference.
for whether to use "array.length" in for loop:
Generally the compiler will do some optimization, as a result it is equivalent to using a variable in the for loop
for "i++" and "++i"
In C++, ++i is preferred and more efficient, but in Java, they are equivalent in this case.
In addition to arshaji response I wanted to know if there was a performance benefit of using size() in a loop vs storing it in advance. I believe the result show that the compiler does optimize things and accessing the length of a list is the same as accessing a variable ( I was worried that the fact it had to go through a function would slow down things).
Here is the time it takes for those two for different method of loop:
for(long i = 0 ; i < mylist.size(); i++){}
VS
for(long i = 0 ; i < 10_000_000; i++){}
Here is the result for a list of ten million elems:
fixed length:
,162,157,151,157,156,159,157,149,150,170,158,153,152,158,151,151,156,156,151,153
getSize:
,164,156,159,154,151,160,162,152,154,152,151,149,168,156,152,150,157,150,156,157
import java.util.ArrayList;
import java.util.List;
public class Main {
final static int LENGTH_SAMPLE = 20;
final static long LENGTH = 10_000_000;
public static void main(String[] args) {
List<Long> mylist = new ArrayList<>();
for(long i = 0 ; i < LENGTH; i++){
mylist.add(i);
}
System.out.println("fixed length:");
for(int i = 0 ; i < LENGTH_SAMPLE; i++){
System.out.printf("," + fixedSize(mylist));
}
System.out.println("");
System.out.println("getSize:");
for(int i = 0 ; i < LENGTH_SAMPLE; i++){
System.out.printf("," + fctSize(mylist));
}
}
private static long fixedSize(List list){
long start = System.currentTimeMillis();
for(long i = 0 ; i < LENGTH; i++){
System.currentTimeMillis();
}
return System.currentTimeMillis() - start;
}
private static long fctSize(List list){
long start = System.currentTimeMillis();
for(long i = 0 ; i < list.size(); i++){
System.currentTimeMillis();
}
return System.currentTimeMillis() - start;
}
}
I want to go through each character in a String and pass each character of the String as a String to another function.
String s = "abcdefg";
for(int i = 0; i < s.length(); i++){
newFunction(s.substring(i, i+1));}
or
String s = "abcdefg";
for(int i = 0; i < s.length(); i++){
newFunction(Character.toString(s.charAt(i)));}
The final result needs to be a String. So any idea which will be faster or more efficient?
As usual: it doesn't matter but if you insist on spending time on micro-optimization or if you really like to optimize for your very special use case, try this:
import org.junit.Assert;
import org.junit.Test;
public class StringCharTest {
// Times:
// 1. Initialization of "s" outside the loop
// 2. Init of "s" inside the loop
// 3. newFunction() actually checks the string length,
// so the function will not be optimized away by the hotstop compiler
#Test
// Fastest: 237ms / 562ms / 2434ms
public void testCacheStrings() throws Exception {
// Cache all possible Char strings
String[] char2string = new String[Character.MAX_VALUE];
for (char i = Character.MIN_VALUE; i < Character.MAX_VALUE; i++) {
char2string[i] = Character.toString(i);
}
for (int x = 0; x < 10000000; x++) {
char[] s = "abcdefg".toCharArray();
for (int i = 0; i < s.length; i++) {
newFunction(char2string[s[i]]);
}
}
}
#Test
// Fast: 1687ms / 1725ms / 3382ms
public void testCharToString() throws Exception {
for (int x = 0; x < 10000000; x++) {
String s = "abcdefg";
for (int i = 0; i < s.length(); i++) {
// Fast: Creates new String objects, but does not copy an array
newFunction(Character.toString(s.charAt(i)));
}
}
}
#Test
// Very fast: 1331 ms/ 1414ms / 3190ms
public void testSubstring() throws Exception {
for (int x = 0; x < 10000000; x++) {
String s = "abcdefg";
for (int i = 0; i < s.length(); i++) {
// The fastest! Reuses the internal char array
newFunction(s.substring(i, i + 1));
}
}
}
#Test
// Slowest: 2525ms / 2961ms / 4703ms
public void testNewString() throws Exception {
char[] value = new char[1];
for (int x = 0; x < 10000000; x++) {
char[] s = "abcdefg".toCharArray();
for (int i = 0; i < s.length; i++) {
value[0] = s[i];
// Slow! Copies the array
newFunction(new String(value));
}
}
}
private void newFunction(String string) {
// Do something with the one-character string
Assert.assertEquals(1, string.length());
}
}
The answer is: it doesn't matter.
Profile your code. Is this your bottleneck?
Does newFunction really need to take a String? It would be better if you could make newFunction take a char and call it like this:
newFunction(s.charAt(i));
That way, you avoid creating a temporary String object.
To answer your question: It's hard to say which one is more efficient. In both examples, a String object has to be created which contains only one character. Which is more efficient depends on how exactly String.substring(...) and Character.toString(...) are implemented on your particular Java implementation. The only way to find it out is running your program through a profiler and seeing which version uses more CPU and/or more memory. Normally, you shouldn't worry about micro-optimizations like this - only spend time on this when you've discovered that this is the cause of a performance and/or memory problem.
Of the two snippets you've posted, I wouldn't want to say. I'd agree with Will that it almost certainly is irrelevant in the overall performance of your code - and if it's not, you can just make the change and determine for yourself which is fastest for your data with your JVM on your hardware.
That said, it's likely that the second snippet would be better if you converted the String into a char array first, and then performed your iterations over the array. Doing it this way would perform the String overhead once only (converting to the array) instead of every call. Additionally, you could then pass the array directly to the String constructor with some indices, which is more efficient than taking a char out of an array to pass it individually (which then gets turned into a one character array):
String s = "abcdefg";
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; i++) {
newFunction(String.valueOf(chars, i, 1));
}
But to reinforce my first point, when you look at what you're actually avoiding on each call of String.charAt() - it's two bounds checks, a (lazy) boolean OR, and an addition. This is not going to make any noticeable difference. Neither is the difference in the String constructors.
Essentially, both idioms are fine in terms of performance (neither is immediately obviously inefficient) so you should not spend any more time working on them unless a profiler shows that this takes up a large amount of your application's runtime. And even then you could almost certainly get more performance gains by restructuring your supporting code in this area (e.g. have newFunction take the whole string itself); java.lang.String is pretty well optimised by this point.
I would first obtain the underlying char[] from the source String using String.toCharArray() and then proceed to call newFunction.
But I do agree with Jesper that it would be best if you could just deal with characters and avoid all the String functions...
Leetcode seems to prefer the substring option here.
This is how I solved that problem:
class Solution {
public int strStr(String haystack, String needle) {
if(needle.length() == 0) {
return 0;
}
if(haystack.length() == 0) {
return -1;
}
for(int i=0; i<=haystack.length()-needle.length(); i++) {
int count = 0;
for(int j=0; j<needle.length(); j++) {
if(haystack.charAt(i+j) == needle.charAt(j)) {
count++;
}
}
if(count == needle.length()) {
return i;
}
}
return -1;
}
}
And this is the optimal solution they give:
class Solution {
public int strStr(String haystack, String needle) {
int length;
int n=needle.length();
int h=haystack.length();
if(n==0)
return 0;
// if(n==h)
// length = h;
// else
length = h-n;
if(h==n && haystack.charAt(0)!=needle.charAt(0))
return -1;
for(int i=0; i<=length; i++){
if(haystack.substring(i, i+needle.length()).equals(needle))
return i;
}
return -1;
}
}
Honestly, I can't figure out why it would matter.