Java arrays speed : copy & re use or create new - java

For an algorithm need a copy of a an array. Have an original and a temp. Need to process "turns" so can re use the temp, but need to start from that state.
After each turn, done with the temp (but need it again for next iteration). Is it better to copy the temp to the original or just assign the original to the temp and make a new array for the temp? Size will be 5x5 to 300x300 2D int array.
//int [][]orig //initialized elsewhere
int [][]newData = new int[orig.length][orig[0].length];
for (int i = 0; i < turns; i++) {
proc1Turn(orig, newData);
//after 1 turn copy newData to orig OR assign to orig
//and create new array for newData?
}
Which will be faster or another way? Will that be pretty much the same (for any system) if we have enough RAM/ free heap for the JVM?

Is it better to copy the temp to the original or just assign the original to the temp and make a new array for the temp?
It is better to do neither. Just swap the array references.
int [][] t = newdata;
newdata = orig;
orig = t;
This avoids allocating a new array (which needs to be cleared by the runtime, and which requires that the previous array be garbage collected at some point).

Related

Create empty array without using List<object>

If I want to create an "unlimited" array I know I can use a list (There is a lot of information on this and other forums)
But what if I don't want to make a list? Is there another way?
Because I want to use a float array in another function and it's kind of a hassle to use a list in this case.
This is what I wrote so far with the listing
List<Float> listfloat = new ArrayList();
listfloat.add((float)0.1); //example
listfloat.add((float)1.2);
float data[]= new float[listfloat.size()];
for(int i = 0; i < listfloat.size(); ++i)
{
data[i] = listfloat.get(i);
}
return data ;
But I would prefer something like this
float data[]; //unknown size
for(i=0 ; i< sizeiwant; i++)
{
data[i] = mydata;
}
return data ;
I know that it will work! I just want to optimise my coding =)
Thank you for reading =)
There are 2 ways you can do this:
You could convert a list to an Array using list.ToArray()
You could dynamically resize the array by changing the size of the array every time you add an element to the array. Here is how you would do that:
//initialize array of size 10.
int[] array=new int[10];
//make copy of array
int[] arrayCopy=array.clone();
//expand array size by 1
array=new int[array.length+1];
//give value to new array index
array[array.length-1]=0;
//copy values from 'arrayCopy' to array
for(int x=0;x<arrayCopy.length;x++){
array[x]=arrayCopy[x];
}
Hope this helped.
With the information you provided I would recommend to use an Array and create a method that is called when your array is full and returns a copy of the original array with more space in this way is you are kind of simulating dynamic size allocation.
Arrays in java are fixed-size, so your second piece of code is never going to work.
If you want a data type that can resize, you should use an ArrayList. On the other hand, there are times when using primitive array like a float[] is quicker and more convenient.
As a result, the need to convert between List<Float> and float[] in the way you do it in the first block of code is fairly common, and there is no way to do it in one line (unless you use an external library).
I advise writing a utility method to do the conversion
public static float[] listToArray(List<Float> list) {
int size = list.size();
float[] temp = new float[size];
for (int i = 0; i < size; i++)
temp[i] = list.get(i);
return temp;
}
(This method could be improved, as it has poor performance for a LinkedList where get is linear).
Annoyingly, you need 8 methods like this for the 8 primitive types, and 8 methods to do the conversions in the other direction. As things stand at the moment, there is no way to write generic code over primitive types, so code duplication like this is common.

How to stop two arrays having the same memory

I have two identical 2D array's of characters however I want to make it so that when I make changes to one it doesn't effect the other. I am assuming it is because they are sharing the same space in memory and was wondering how to stop this.
private char[][] a;
private char[][] b;
a = new char[8][];
b = new char[8][];
while(file.hasNext()) //reads 8 lines from a file and adds it to text to both arrays
{
char[] constant = file.nextLine().toCharArray();
a[i] = constant;
b[i] = constant;
i++;
}
then if i were to run the code
a[0][0] = 't';
then it also changes b[0][0] to 't'
Arrays are objects. When you assign them like this
int[][] firstArray = getArray(); // Get your array from somewhere
int[][] secondArray = firstArray; // Assign an array
you have only one array, but you have a second variable that references it. Essentially, secondArray[i][j] and firstArray[i][j] refer to the same object in memory by two different names.
To fix this, make a copy of the array. A simple way of doing it is to call the clone() method on the original array, like this:
int[][] secondArray = new int[firstArray.length][];
for (int i = 0 ; i != secondArray.length ; i++) {
secondArray[i] = (int[])firstArray[i].clone();
}
Note: clone() creates a shallow copy. If you
My first idea was:
char[] orig = // something;
char[] copy = orig.clone();
But be aware:
clone() only creates a shallow copy of an array. That means for a 2D-Array with chars you have to clone each subarray.
For further information about clone() click here.
Your code should look something like this
char[][] original = new char[3][3];
char[][] copy = new char[orignal.length][0];
for(int i = 0; i < original.length; i++){
copy[i] = original[i].clone();
}
I have two identical 2D array's of characters however I want to make it so that when I make changes to one it doesn't effect the other. I am assuming it is because they are sharing the same space in memory and was wondering how to stop this.
Arrays don't share memory. Nor do any other variables in Java.
Ergo if changes to one affect the other, you don't have two arrays at all. You only have one, with two references to it. Updating the array via one reference is visible via the other reference.
The solution is therefore to create two arrays, not just one.

How to copy a array into another array that already has data in it?

How would I copy an array say
float arraytobecopied[] = {1.20,2.50,3.60};
to another array that has data in it already say
float newarray[] = {5.20,6.30,4.20};
I want to add the the arraytobecopied to the end of the new array and keep the values in the array. also as a side note this would be an on going process adding to the end of the array every time.
Should i just use a for loop? or is there a better way.
(Can't use Array) already tried:(
This question has been asked here before, You can see this page for the answer. How can I concatenate two arrays in Java?
Use System.arraycopy
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
You can't increase the size of the original array. But you could create a new array, copy both source arrays into it, and assign your reference variable to it.
For example, here's a sketch of a simple implementation. (An alternative is to use System.arraycopy().)
float[] newerArray = new float[ newarray.length + arraytobecopied.length ];
for ( int i = 0; i < newarray.length; ++i ) {
newerArray[i] = newarray[i];
}
for ( int i = 0; i < arraytobecopied.length; ++i ) {
newerArray[ newarray.length + i ] = arraytobecopied[i];
}
newarray = newerArray; // Point the reference at the new array
Alternatively, you could use a java.util.ArrayList, which automatically handles growing the internal array. Its toArray() methods make it easy to convert the list to an array when required.
The easiest approach from a programming perspective is to use a List<Float> (if you can use Float values instead of float) or a third-party library such as Apache Commons Collections or Trove that provides dynamic arrays of primitives.
If you need to use a simple array of primitives (and not a wrapper class), you can use a couple of methods in the java.util.Arrays and java.lang.System classes to help:
int len1 = newarray.length;
int len2 = arraytobecopied.length;
float[] result = Arrays.copyOf(newarray, len1 + len2);
System.arraycopy(arraytobecopied, 0, result, len1, len2);
// result now contains the concatenation of newarray and arraytobecopied
Note that you cannot change the length of an array object; you can only reassign the variable to a new array (e.g., newarray = result;).
The easiest can be:
List<Float> floats = new ArrayList(arraytobecopied);
floats.addAll(newarray);
arraytobecopied = floats.toArray(new float[0]);
If you dont want to use anything from java.Util at all.
How about writing one method that updates the destination array with src array. Now when u copy elements make sure that the size is enough in destination array. Otherwise when you create a new array, create it with double size and copy the elements, this may help in avoiding a new array creation everytime and doing iterations to populate the complete array again after resizing.
Somewhat similar to how array list maintains size of array inside it.

Java int[][] array object

I have defined an int[][] object. Because it is an object, if i send it to a method as a parameter, it will only send it's reference, so any changes to the array in the method, will influence it in the main program. So i would like to make a clone of this object inside the method, but i'm not sure how to accomplish this.
I was thinking of something like so:
private void myMethod( int[][] array )
{
//Define our temporary array (clone)
int[][] newArray = new int[3][3];
//Go through the elements of the array
for .... row = 0; row < ..; row++
for ..... col = 0; col < ..; col++
//Copy individual elements from one array to another
newArray[row][col] = array[row][col];
}
but will the above code copy each element from array into newArray as value (so... a clone of the item), or just the reference?
If so, how can this be accomplished. If i were to use ArrayLists instead of int[][] objects, there is the clone() method or something like that, but i haven't got that method for int[][] objects :(
Also, if i'm not mistaken if i do this inside the method newArray = array , that will copy just the reference again, so both will point to the same int[][] object :(
P.S. I know i could just test this, but i'd like to discuss it with you guys a bit, and see what's what exactly.
but will the above code copy each element from array into newArray as value (so... a clone of the item), or just the reference?
You're copying each element of the array, and each element is an int, so you're fine. The new array will be completely independent of the original.
Note that if instead you'd done:
int[][] newArray = new int[3][];
for (int i = 0; i < 3; i++) {
newArray[i] = array[i];
}
... then that would just have copied references to the three existing int[] arrays into newArray. But you've allocated a completely new set of arrays (one int[][] and 3x int[]) so it's all independent.
You could use clone() on the matrix and on each array corresponding to a row in the matrix, it will work without problems because you're cloning a matrix of primitive values, like this:
int[][] matrix = new int[3][3];
// ... matrix gets filled ...
int[][] copy = matrix.clone();
for (int i = 0; i < matrix.length; i++)
copy[i] = matrix[i].clone();
The above will create a copy matrix which is independent of matrix, meaning that you can change the values of the copy without affecting the original.
Primitive types, such as int, are not reference types. Thus, going through all the items and copying them one by one will make a copy-by-value.
In short, your code is correct.
int is a primitive type, you always pass them around as value, not as reference, so you code will indeed create a new copy of the array.
You might want to consider using Arrays.copyOf(), it may be faster.

How to filter an array in Java?

How can I filter an array in Java?
I have an array of objects, for example cars:
Class:
public class Car{
public int doors;
public Car(int d){
this.doors = d;
}
}
Use:
Car [] cars = new Cars[4];
cars[0] = new Car(3);
cars[1] = new Car(2);
cars[2] = new Car(4);
cars[3] = new Car(6);
Now I want to filter the array of cars, keeping only 4 doors and more:
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
//add cars[i] to a new array
}
}
How should I do this?
Before I did it with a Vector:
Vector subset = new Vector();
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
//add cars[i] to a new array
subset.addElement(cars[i]);
}
}
And then I would make a new array with the size of the Vector. Then I would loop over the vector again and fill the new array. I know this is a very large procedure for something simple.
I'm using J2ME.
EDIT: saw that ArrayList is not in J2ME, but based on documentation, it does have a Vector. If that Vector class is different than J2SE Vector (as this documentation indicates), then perhaps the following code would work:
Vector carList = new Vector();
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
carList.addElement(cars[i]);
}
}
Car[] carArray = new Car[carList.size()];
carList.copyInto(carArray);
The most efficient way to do this--if the predicate you're filtering on is inexpensive and you're accessing it with a single thread--is usually to traverse the list twice:
public Car[] getFourDoors(Car[] all_cars) {
int n = 0;
for (Car c : all_cars) if (c.doorCount()==4) n++;
Car[] cars_4d = new Car[n];
n = 0;
for (Car c : all_cars) if (c.doorCount()==4) cars_4d[n++] = c;
return cars_4d;
}
This traverses the list twice and calls the test twice, but has no extra allocations or copying. The Vector-style methods traverse the list once, but allocates about twice the memory it needs (transiently) and copies every good element about twice. So if you are filtering a tiny fraction of the list (or performance isn't an issue, which very often it isn't), then the Vector method is good. Otherwise, the version above performs better.
If you really need a plain array as the result, I think your way is the way to go: you don't know the number of resulting elements before you filter, and you can't construct a new array without knowing the number of elements.
However, if you don't need thread-safety, consider using ArrayList instead of a Vector. It ought to be somewhat faster. Then use ArrayList's toArray method to get the array.
I can't see much wrong with your code. You could just stick with Vectors throughout though.
You could simplify the second part (where you copy the matching items into the new array) using Vector.copyInto(Object[]).
There's no direct way to remove elements from an array; its size is fixed. Whatever you do, you need to allocate a new array somehow.
If you want to avoid the minor memory overhead of allocating a Vector, another option would be to make two passes over your array. The first time, simply count the number of elements that you want to keep. Then allocate an array that size, and loop over your old array again, copying matching elements into the new array.
You can use System.arrayCopy():
Car[] cars = ...
int length = cars.length < 4 ? cars.length() : 4;
Car filter = new Car[4];
System.arrayCopy(cars, 0, filter, 0, length);
UPDATE: System.arrayCopy is available in Java ME API, unlike Vector.subList(). Thanks for the correction.
You will need to create a new array anyway.
Vector vector = new Vector(array.length);
for (int i = 0; i < array.length; i++) {
if (array[i].doors > 4) {
vector.add(array[i]);
}
}
Car[] result = new Car[vector.size()];
vector.copyInto(result);
This isn't quite efficient, though.

Categories