I'm newbie Java learner. I'm trying to understand how can I write efficient codes in terms of both performance and readability. At this point arrays have been a puzzle for me. Six primitive tests are below. Their first three and second three return almost same times. Please explain what is going on.
String s= "";
int[] Array1=new int[100000];
Long startingTime=System.nanoTime();
for (int i = 0; i < Array1.length; i++) {
s+=i;
}
System.out.println("time : " + (System.nanoTime()-startingTime));
String s= "";
int length=100000;
Long startingTime=System.nanoTime();
for (int i = 0; i < length; i++) {
s+=i;
}
System.out.println("time : " + (System.nanoTime()-startingTime));
String s= "";
int length1=50000;
int length2=50000;
Long startingTime=System.nanoTime();
for (int i = 0; i < length1+length2; i++) {
s+=i;
}
System.out.println("time : " + (System.nanoTime()-startingTime));
public class Test3Length {
static class Foo {
int mSplat = 0;
}
public static void main(String[] args) {
int twentyMillions = 20000000;
Foo[] mArray = new Foo[twentyMillions];
for (int i = 0; i < mArray.length; i++) {
mArray[i] = new Foo();
}
int sum = 0;
Long startingTime = System.nanoTime();
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
System.out.println("time : " + (System.nanoTime() - startingTime));
}
}
public class Test4Length {
static class Foo {
int mSplat = 0;
}
public static void main(String[] args) {
int twentyMillions = 20000000;
Foo[] mArray = new Foo[twentyMillions];
for (int i = 0; i < mArray.length; i++) {
mArray[i] = new Foo();
}
int sum = 0;
Long startingTime = System.nanoTime();
for (int i = 0; i < twentyMillions; ++i) {
sum += mArray[i].mSplat;
}
System.out.println("time : " + (System.nanoTime() - startingTime));
}
}
public class Test5Length {
static class Foo {
int mSplat = 0;
}
public static void main(String[] args) {
int twentyMillions = 20000000;
Foo[] mArray = new Foo[twentyMillions];
for (int i = 0; i < mArray.length; i++) {
mArray[i] = new Foo();
}
int sum = 0;
Long startingTime = System.nanoTime();
for (Foo a : mArray) {
sum += a.mSplat;
}
System.out.println("time : " + (System.nanoTime() - startingTime));
}
}
First question, would I prefer to int length in for-loop condition rather than array.length?
Second question, would I prefer a foreach loop rather than for-loop unless array is collection?
In real life it does not really matter if you use foreach or for loop. The performance difference is barely noticible. If you need the current index then do for loop, if not then go with foreach. As for the length, it is just a property, and since it is an array it is set when the array is initialized and never change. Reading the value of a property takes almost no time at all. Thus for readability's sake put it inside for loop's condition
First question, would I prefer to int length in for-loop condition rather than array.length?
That literally makes no difference. array.length is an invariant, so the JIT will only access it once anyway, making its value identical to a local variable in terms of performance.
Second question, would I prefer a foreach loop rather than for-loop unless array is collection?
When the object you loop over is an array, the translation of a foreach-loop is the same as a for-loop, so that makes no difference whatsoever.
However, in conclusion I should say that you seem to be focusing on the wrong things. In your first three tests, virtually all of your run-time is likely to be spent on the s+=i expression, since each evaluation creates a new String in order to add i to it. You will probably see much more massive speed-ups by using a StringBuilder instead of trying different variants of the looping construct.
Related
I have this code sample with a method which returns the sum of array values. But instead of the sum, I'm getting 0.
This is my code sample
class Calculation {
int answer;
public int SumOfArrays(int data[], int size) {
answer = 0;
for (int i = data[0]; i < size; i++) {
answer += data[i];
//System.out.println(data[i]);
}
return answer;
}
class Main {
public static void main(String[] args) {
Calculation cal = new Calculation();
int data[]={10,20};
System.out.println(cal.SumOfArrays(data, 2));
}
}
can anyone tell me what;s wrong with my code?
The loop doesn't run at all - the condition data[0] < size is false, so the initial value of answer = 0 is returned.
To make it work, change the statement to (int i = 0; i < size; i++). Also, size might be replaced with data.length.
This is your code with minor corrections. Try it.
class Calculation {
public int SumOfArrays(int data[]) {
int answer = 0; // this is just better
for (int i = 0; i < data.length; i++) {
answer += data[i];
}
return answer;
}
class Main {
public static void main(String[] args) {
Calculation cal = new Calculation();
int data[]={10,20};
System.out.println(cal.SumOfArrays(data));
}
}
The counter i for the for loop is incorrectly initialized. You have initialized it to the value of first element in the array instead of 0. Initialize it to 0 as shown below:
for (int i = 0; i < size; i++) {
answer += data[i];
//System.out.println(data[i]);
}
As you can see from your loop
for(int i = data[0]; i < size; i++)
the variable i is equals to the first element in the data array which means that is greater then the size variable ..so the loop will not begin at all
to fix the problem change your loop to this
for (int i = 0; i < size; i++) {
answer += data[i];
//System.out.println(data[i]);
}
I want to write a java program which will calculate the first 20 factorial and store them in an array. Then go through the array and sum all of the items and print the result on the screen.
Here is my code but I think I did something wrong:
public class ArrayQuestion4 {
public static void main(String[] args) {
long array[]= new long[20];
long temp=1;
for ( int i=1; i<20; i++){
temp = i*(i+1);
temp = temp*(temp+1);
array[i]=temp;
System.out.println(array[i]);
}
for ( int i=1; i<20; i++){
temp = array[i];
temp = array[i]+(array[i+1]);
temp = temp+(temp+1);
System.out.println(temp);
}
}
}
The answer that comes out is not correct by the way.
I figure it out the correct code is this:
public class ArrayQuestion4 {
public static void main(String[] args) {
long array[]= new long[20];
array[0]=1;
long temp=0;
for ( int i=1; i<20; i++){
array[i]=array[i-1]*(i+1);
System.out.println(array[i-1]+"*"+(i+1)+" = "+array[i]);
}
for ( int i=1; i<20; i++){
temp = temp + array[i-1] + array[i];
}
System.out.println(" ");
System.out.println("Sum = "+temp);
}
}
The way you define factorial of n is
fact(n) = n * fact(n-1)
In the solution, factorial[n] represents factorial(n).
and temp is the current factorial being calculated.
public static void main(String[] args) {
long factorial[] = new long[20];
//Because Fact(1) = 1 * Fact(0), and fact(0) = 1.
factorial[0] = 1;
for (int n = 1; n < 20; n++) {
// Loop needs to be <20 because i have defined the array size = 20.
// <= would get an array out of bound exception. You can change the limits as you want.
//calculating the factorial based on formula:
// Factorial(N) = n * Facorial(N-1);
long factorialOfN = n*factorial[n-1];
//storing back the value in the array for future use.
factorial[n] = factorialOfN;
//Printing it.
System.out.println(factorialOfN);
}
}
As an illustration of where the code is probably not doing what you want it to be doing, look at what you get for (2)!
temp = i*(i+1); //temp = 1*(1+1); which is 2
temp = temp*(temp+1); //temp = 2*(2+1); which is 6
array[i] = temp; //array[1] = 6; - also note we skip ever assigning array[0]
You get 6 as an answer, which is incorrect.
Long could not hold sum of all 20! results. There is a limit for 'long' in Java and it is
public static final long MAX_VALUE = 0x7fffffffffffffffL;
which is 9223372036854775807
Use 'BigInteger' to get correct answer. And also refer 'How (not) to write Factorial in Java'
Switching from Python to Java and decided to code an insertionsort method. I have written this in Python and tried to switch over the code one-to-one, it all seems good to go but it is not functioning correctly. I cut out all the other class methods/data fields to converse space and tried to limit this code only to that which is relevant to this question:
public class test1 {
static final int NOT_FOUND = -1; // A constant
// Attributes (just one)
private double data[];
// Constructor
test1 (double data[]) {
this.data = data.clone();
}
double getItem (int key) {
return data[key];
}
void insertionSort () {
for (int i = 1;i >= data.length;i++){
double currentElement = data[i];
int k = i - 1;
while(k>=0 & data[k] > currentElement){
data[k+1] = data[k];
k -= 1;
data[k + 1] = currentElement;
}
}
}
public static void main(String[] arg){
double testData[] = {1,4,32,5,673,145,68,14,757};
test1 b = new test1 (testData);
b.insertionSort();
//See how array has changed
for (int i = 0; i < 9; i++) {
System.out.print(b.getItem(i) + ", ");
}
}
}
Change
for (int i = 1; i >= data.length; i++)
to
for (int i = 1; i < data.length; i++)
The reason behind it is that you are retrieving an item from the array data for the index of i. The loop did not work because i was initialized to 1 and the condition i >= data.length was returning false because i is actually smaller than the length of the data array in your example, hence the loop did not run.
There are other troubles with this kind of check in the for loop when retrieving an element from an array because if an index for which you are returning the element is >= than the length of the array you will get an IndexOutOfBoundsException.
I am sure this is not what you meant:
for (int i = 1;i >= data.length;i++){
This will be either an infinite(actually up to overflow) or an empty cycle.
I know that is not exactly what are you asking, but if you are learning Java, maybe you could find useful:
In Java you can use Arrays.sort() :
void insertionSort () {
Arrays.sort(data);
}
I am getting an error when making the call to method findPosition. What I'm trying to do with the program is measure how long the algorithm runs on average, over 1000 iterations of it. Then I want to call the method and find the position of the value (if it is found) in the array. I'm getting a compiler error that the arguments being passed do not match the method. Specifically, the second argument is being taken as an int, even though I want to pass the value in an array. I can't find my error and am new to working with arrays, so thank you in advance if you can tell me where my mistake is.
import java.util.*;
public class AlgorithmRuntime
{
static int num = 0;
static long total = 0;
static long average = 0;
public static void main (String[] args)
{
boolean isValueInArray;
int searchValue;
do {
// 1. Setup
int size = 1000;
long sum = 0;
int[] iArray = new int[size];
Random rand = new Random(System.currentTimeMillis());
for (int i = 0; i < size; i++)
iArray[i] = rand.nextInt();
searchValue = rand.nextInt(1000) + 1;
// 2. Start time
long start = System.nanoTime();
// 3. Execute algorithm
for (int j = 0; j < size; j++)
{
if (iArray[j] == searchValue)
{
isValueInArray = true;
}
if (isValueInArray == true)
findPosition(searchValue, iArray[isValueInArray]);
}
// 4. Stop time
long stop = System.nanoTime();
long timeElapsed = stop - start;
total = total + timeElapsed;
num++;
} while (num < 1000);
average = total / 1000;
System.out.println("The algorithm took " + average
+ " nanoseconds on average to complete.");
}
}
public int findPosition(int valueOfInt, int[] array)
{
for (int i = 0; i < array.length; i++)
if (array[i] == valueOfInt)
return i;
return -1;
}
findPostion method accepts two arguments; one of type int and another of type int array. Here is the signature of findPosition:
public int findPosition(int valueOfInt, int[] array)
but you are passing it two int values as mentioned here:
findPosition(searchValue, iArray[isValueInArray];
isArray is an int array but iArray[isValueInArray] is an int value at index isValueInArray.
You need to pass an array as the second param instead of an int value.
You need to pass in
if (isValueInArray == true) {
findPosition(searchValue, iArray);
}
iArray[isValueInArray] will give you an int value and not the array.
I just recently finished an android project and I have done some extensive codes of ArrayList and doing looping stuffs on it. I have two sets example of loops here.
ArrayList<SomeObject> object = new ArrayList<SomeObject>();
for(int c=0;c<object.size();c++){
}
for(SomeObject obj: object){
}
I think the second one is good if you don't need the incrementing value and I think far more readable and neat than the first. But what in the two loops is ideal or efficient to use in terms speed, performance and memory usage?
As per suggestions from the Android Documentation the most efficient ways for making loop are:
public void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
public void two() {
int sum = 0;
for (Foo a : mArray) {
sum += a.mSplat;
}
}
Please, note that these ways have same performance for devices with JIT. So, in cases then JIT is off (e.g. while debugging using Eclipse) You might observe different results (two() will be faster than one())
Update
I've checked ArrayLists also by using the following code:
final ArrayList<String> testArrayList = new ArrayList<String>(1000);
for (int i = 0; i < 1000; i++) {
testArrayList.add(String.valueOf(i<<2));
}
final TimingLogger timings = new TimingLogger("Loop", "ArrayLists");
timings.addSplit("start");
for (int loopCount = 0; loopCount < 1000; loopCount++) {
int sum = 0;
for (int i = 0; i < testArrayList.size(); i++) {
sum += Integer.valueOf(testArrayList.get(i));
}
}
timings.addSplit("zero()");
for (int loopCount = 0; loopCount < 1000; loopCount++) {
int sum = 0;
final int len = testArrayList.size();
for (int i = 0; i < len; i++) {
sum += Integer.valueOf(testArrayList.get(i));
}
}
timings.addSplit("one()");
for (int loopCount = 0; loopCount < 1000; loopCount++) {
int sum = 0;
for (String item : testArrayList) {
sum += Integer.valueOf(item);
}
}
timings.addSplit("two()");
timings.dumpToLog();
And obtained the following output (with JIT):
ArrayLists: begin
ArrayLists: 0 ms, start
ArrayLists: 2713 ms, zero()
ArrayLists: 1753 ms, one()
ArrayLists: 1922 ms, two()
ArrayLists: end, 6388 ms
So, we able to see, that variants one() and two() provides similar results, and these results are faster than zero() (so, results look similar to ones described in the documentation for arrays).