References Mutability in Java summing two vectors - java

I am new to Java and I am following a class, however in one of the exercises I came up with a doubt when comparing my answer vs. teacher.
Say I have a class that holds as attributes the coefficients of a polynomial and I now want to add two polynomials.
In the teacher solution (method add_1) he makes a copy of the coefficients of both arrays being summed, however from what I understood so far Doubles are immutable, so I assume I donĀ“t need to use a copy, but only address directly (method add_2). I have tested an my values in the array are not mutated, however I wanted to confirm my understanding.
public class Polynomial {
// coefficient at index k belongs to term x^k
// consistency: array is always present and contains at least one number (which
// may be zero)
private double[] coefficients;
// --------------------- constructors
// ----------------------------------------------
// constructor: zero polynomial
public Polynomial() {
coefficients = new double[1];
coefficients[0] = 0;
}
public static Polynomial add_1(Polynomial f, Polynomial g) { // Option 1
double[] f_array = f.getCoefficients();//Do I need this copy?
double[] g_array = f.getCoefficients();//Do I need this copy?
int n = Math.max(f_array.length, g_array.length); // new array needs to be this long
double[] target = new double[n];
// fastest way to do it without if-statements:
for (int k = 0; k < n; k = k + 1) {
target[k] = 0;//Zero vector array
}
for (int k = 0; k < f_array.length; k = k + 1) {
target[k] = target[k] + f_array[k];
}
for (int k = 0; k < g_array.length; k = k + 1) {
target[k] = target[k] + g_array[k];
}
// Turn array into an object
Polynomial p = new Polynomial();
p.setCoefficients(target);
return p;
}
public static Polynomial add_2(Polynomial f, Polynomial g) { // Option 2
int n = Math.max(f_array.length, g_array.length); // new array needs to be this long
double[] target = new double[n];
// fastest way to do it without if-statements:
for (int k = 0; k < n; k = k + 1) {
target[k] = 0;//Zero vector array
}
for (int k = 0; k < f.coefficients.length; k = k + 1) {
target[k] = target[k] + f.coefficients[k];
}
for (int k = 0; k < g.coefficients.length; k = k + 1) {
target[k] = target[k] + g.coefficients[k];
}
// Turn array into an object
Polynomial p = new Polynomial();
p.setCoefficients(target);
return p;
}
// --------------------- setter / getter methods
// -----------------------------------
// setter for coefficients, creates a copy(!) of coefficients and stores it
public void setCoefficients(double[] coefficients) {
this.coefficients = new double[coefficients.length];
for (int k = 0; k < coefficients.length; k = k + 1) {
this.coefficients[k] = coefficients[k];
}
}
// getter for coefficients, returns a copy(!) of the polynomials coefficients
public double[] getCoefficients() {
double[] copy = new double[coefficients.length];
for (int k = 0; k < coefficients.length; k = k + 1) {
copy[k] = coefficients[k];
}
return copy;
}
}
Is my method add_2 protected against mutation or is there any reason I should use a copy?
Many thanks

double[] f_array = f.getCoefficients();//Do I need this copy?
This belies a misunderstanding of java.
f.getCoefficients() doesn't return a double array. That is impossible; java can only return primitives and references. It returns a reference to a double array.
No copy of an array is being made here. The only copies java makes implicitly are of references and primitives; any other copying is something you'd have to do explicitly using e.g. a copy() or clone() or Arrays.copyOf invocation. All that you've done here is make a copy of the reference which doesn't matter. f.getCoefficients() already returns a copy of the reference.
Let me try to explain with an example:
class Example {
double[] array = new double[10];
public static void main(String[] args) {
Example ex = new Example();
double[] arr = ex.array;
arr[0] = 1;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
ex.array[0] = 2;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
arr = new double[20];
arr[0] = 20;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
}
}
> 1
> 1
> 2
> 2
> 20
> 2
Initially there is only one array, and both ex.array and arr are references pointing to this array. arr[0] = is dereferencing the reference and doing an operation on what you find there, thus, whilst arr and ex.array are copies, it's a copy of the same reference, and just like if I make a copy of a treasure map and hand it to you, if you then follow your map, dig down, and steal the treasure, and then later I follow my copy, I find the treasure gone - so it is here: arr[0] = 1 affects the one and only array, and thus printing ex.array[0[] also shows 1.
Later, with arr = new double[20] we first make a new object (new double[20]) and then assign a reference to this newly created object to arr, which has no effect on ex.array. Thus, now, it's like you have a treasure map to a completely different treasure vs. my ex.array treasure map. Therefore, when you follow your map, dig down, and put a 20 in the box, if I follow my map, I do not see that, hence why the last 2 lines prints 20 and 1, and not 20 and 20.

Related

Adding elements to the beginning of an array of ints

Working on an addBefore() method that adds a new element to the beginning of an array of ints and then causes the existing elements to increase their index by one.
This is what is showing in the console when trying to run --
java.lang.RuntimeException: Index 1 should have value 11 but instead has 0
at IntArrayListTest.main(IntArrayListTest.java:67)
Below is the code I have so far.
public class IntArrayList {
private int[] a;
private int length;
private int index;
private int count;
public IntArrayList() {
length = 0;
a = new int[4];
}
public int get(int i) {
if (i < 0 || i >= length) {
throw new ArrayIndexOutOfBoundsException(i);
}
return a[i];
}
public int size() {
return length;
}
public void set(int i, int x) {
if (i < 0 || i >= a.length) {
throw new ArrayIndexOutOfBoundsException(i);
}
a[i] = x;
}
public void add(int x) {
if (length >= a.length) {
int[] b = new int[a.length * 2];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
a = b;
//count += 1;
}
a[length] = x;
count++;
length = length + 1;
}
public void addBefore(int x) {
int[] b = new int[a.length*2];
for (int i = 0; i < a.length; i++) {
b[i+a.length] = a[i];
}
a = b;
a[index] = x;
length ++;
}
}
Whether you add first or last, you need to only grow the array size if it is already full.
The count field seems to be exactly the same as length, and index seems unused and meaningless as a field, so remove them both.
To rearrange values in an array, use this method:
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
You two "add" methods should then be:
public class IntArrayList {
private int[] a; // Underlying array
private int length; // Number of added elements in a
// other code
public void add(int x) {
if (length == a.length) {
int[] b = new int[a.length * 2];
System.arraycopy(a, 0, b, 0, length);
a = b;
}
a[length++] = x;
}
public void addBefore(int x) {
if (length < a.length) {
System.arraycopy(a, 0, a, 1, length);
} else {
int[] b = new int[a.length * 2];
System.arraycopy(a, 0, b, 1, length);
a = b;
}
a[0] = x;
length++;
}
}
If the answer requires you to do the looping yourself then something like this should work fine (one of a few ways to do this, but is O(n)) :
public void addBefore(int x) {
if(length + 1 >= a.length){
int[] b = new int[a.length*2];
b[0] = x;
for (int i = 0; i < length; i++) {
b[i + 1] = a[i];
}
a = b;
} else {
for (int i = length; i >= 0 ; i--) {
a[i + 1] = a[i];
}
a[0] = x;
}
length++;
}
I noticed this started running a "speed test" - not sure how useful a test like that is, as it would be based on cpu performance, rather than testing complexity of the algorithm ..
you had three problems with your solution:
you increased the length of a every time the method was called. this would quickly create an OutOfMemoryException
when you copied values from a to b, you did b[i+a.length] = a[i]; which means the values would be copied to the middle of b instead of shift just one place
at the end, you put the new value in the end of the array instead of at the beginning.
all this I was able to see because I used a debugger on your code. You need to start using this tool if you want to be able to detect and fix problems in your code.
so fixed solution would do this:
check if a is full (just like it is done with add() method) and if so, create b, and copy everything to it and so on)
move all values one place ahead. the easiest way to do it is to loop backwards from length to 0
assign new value at the beginning of the array
here is a working solution:
public void addBefore(int x) {
// increase length if a is full
if (length >= a.length) {
int[] b = new int[a.length * 2];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
a = b;
}
// shift all values one cell ahead
for (int i = length; i > 0; i--) {
a[i] = a[i-1];
}
// add new value as first cell
a[0] = x;
length ++;
}
}
You can use the existing Java methods from the Colt library. Here is a small example that uses a Python syntax (to make the example code small I use Jython):
from cern.colt.list import IntArrayList
a=IntArrayList()
a.add(1); a.add(2) # add two integer numbers
print "size=",a.size(),a
a.beforeInsert(0, 10) # add 10 before index 0
print "size=",a.size(),a
You can use DataMelt program to run this code. The output of the above code is:
size= 2 [1, 2]
size= 3 [10, 1, 2]
As you can see, 10 is inserted before 1 (and the size is increased)
Feel free to change the codding to Java, i.e. importing this class as
import cern.colt.list.IntArrayList
IntArrayList a= new IntArrayList()
You could use an ArrayList instead and then covert it to an Integer[] Array which could simplify your code. Here is an example below:
First create the ArrayList:
ArrayList<Integer> myNums = new ArrayList<Integer>();
Next you can add the values that you want to it, but I chose to just add the numbers 2-5, to illustrate that we can make the number 1 the first index and automatically increment each value by one index. That can simplify your addBefore() method to something such as this:
public static void addBefore(ArrayList<Integer> aList) {
int myInt = 1;
aList.add(0, myInt);
}
Since your ArrayList has ONE memory location in Java, altering the Array within a method will work (this would also work for a regular Array). We can then add any value to the beginning of the ArrayList. You can pass an Integer to this method as the second argument (int x), if you want, but I simply created the myInt primitive to simplify the code. I know that in your code you had the (int x) parameter, and you can add that to this method. You can use the ArrayList.add() method to add the int to index 0 of the Array which will increment each Array element by 1 position. Next you will need to call the method:
addBefore(myNums);//You can add the int x parameter and pass that as an arg if you want here
Next we can use the ArrayList.toArray() method in order to covert the ArrayList to an Integer Array. Here is an example below:
Integer[] integerHolder = new Integer[myNums.size()];
Integer[] numsArray = (Integer[])myNums.toArray(integerHolder);
System.out.println(Arrays.toString(numsArray));
First we create an ArrayHolder that will be the same size as your ArrayList, and then we create the Array that will store the elements of the ArrayList. We cast the myNums.toArray() to an Integer Array. The results will be as follows. The number 1 will be at index 0 and the rest of your elements will have incremented by 1 index:
[1, 2, 3, 4, 5]
You could do the entire process within the addBefore() method by converting the Array to an ArrayList within the method and adding (int x) to the 0 index of the ArrayList before converting it back into an Array. Since an ArrayList can only take a wrapper class object you'll simply need to convert the int primitive Array into the type Integer for this to work, but it simplifies your addBefore() method.

Is it possible to cut down or add up an initialized array? [duplicate]

I have searched for a way to resize an array in Java, but I could not find ways of resizing the array while keeping the current elements.
I found for example code like int[] newImage = new int[newWidth];, but this deletes the elements stored before.
My code would basically do this: whenever a new element is added, the array largens by 1. I think this could be done with dynamic programming, but I'm, not sure how to implement it.
You can't resize an array in Java. You'd need to either:
Create a new array of the desired size, and copy the contents from the original array to the new array, using java.lang.System.arraycopy(...);
Use the java.util.ArrayList<T> class, which does this for you when you need to make the array bigger. It nicely encapsulates what you describe in your question.
Use java.util.Arrays.copyOf(...) methods which returns a bigger array, with the contents of the original array.
Not nice, but works:
int[] a = {1, 2, 3};
// make a one bigger
a = Arrays.copyOf(a, a.length + 1);
for (int i : a)
System.out.println(i);
as stated before, go with ArrayList
Here are a couple of ways to do it.
Method 1: System.arraycopy():
Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array. A subsequence of array components are copied from the source array referenced by src to the destination array referenced by dest. The number of components copied is equal to the length argument. The components at positions srcPos through srcPos+length-1 in the source array are copied into positions destPos through destPos+length-1, respectively, of the destination array.
Object[] originalArray = new Object[5];
Object[] largerArray = new Object[10];
System.arraycopy(originalArray, 0, largerArray, 0, originalArray.length);
Method 2: Arrays.copyOf():
Copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values. For any indices that are valid in the copy but not the original, the copy will contain null. Such indices will exist if and only if the specified length is greater than that of the original array. The resulting array is of exactly the same class as the original array.
Object[] originalArray = new Object[5];
Object[] largerArray = Arrays.copyOf(originalArray, 10);
Note that this method usually uses System.arraycopy() behind the scenes.
Method 3: ArrayList:
Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)
ArrayList functions similarly to an array, except it automatically expands when you add more elements than it can contain. It's backed by an array, and uses Arrays.copyOf.
ArrayList<Object> list = new ArrayList<>();
// This will add the element, resizing the ArrayList if necessary.
list.add(new Object());
You could just use ArrayList which does the job for you.
It is not possible to change the Array Size.
But you can copy the element of one array into another array by creating an Array of bigger size.
It is recommended to create Array of double size if Array is full and Reduce Array to halve if Array is one-half full
public class ResizingArrayStack1 {
private String[] s;
private int size = 0;
private int index = 0;
public void ResizingArrayStack1(int size) {
this.size = size;
s = new String[size];
}
public void push(String element) {
if (index == s.length) {
resize(2 * s.length);
}
s[index] = element;
index++;
}
private void resize(int capacity) {
String[] copy = new String[capacity];
for (int i = 0; i < s.length; i++) {
copy[i] = s[i];
s = copy;
}
}
public static void main(String[] args) {
ResizingArrayStack1 rs = new ResizingArrayStack1();
rs.push("a");
rs.push("b");
rs.push("c");
rs.push("d");
}
}
You could use a ArrayList instead of array. So that you can add n number of elements
List<Integer> myVar = new ArrayList<Integer>();
Standard class java.util.ArrayList is resizable array, growing when new elements added.
You can't resize an array, but you can redefine it keeping old values or use a java.util.List
Here follows two solutions but catch the performance differences running the code below
Java Lists are 450 times faster but 20 times heavier in memory!
testAddByteToArray1 nanoAvg:970355051 memAvg:100000
testAddByteToList1 nanoAvg:1923106 memAvg:2026856
testAddByteToArray1 nanoAvg:919582271 memAvg:100000
testAddByteToList1 nanoAvg:1922660 memAvg:2026856
testAddByteToArray1 nanoAvg:917727475 memAvg:100000
testAddByteToList1 nanoAvg:1904896 memAvg:2026856
testAddByteToArray1 nanoAvg:918483397 memAvg:100000
testAddByteToList1 nanoAvg:1907243 memAvg:2026856
import java.util.ArrayList;
import java.util.List;
public class Test {
public static byte[] byteArray = new byte[0];
public static List<Byte> byteList = new ArrayList<>();
public static List<Double> nanoAvg = new ArrayList<>();
public static List<Double> memAvg = new ArrayList<>();
public static void addByteToArray1() {
// >>> SOLUTION ONE <<<
byte[] a = new byte[byteArray.length + 1];
System.arraycopy(byteArray, 0, a, 0, byteArray.length);
byteArray = a;
//byteArray = Arrays.copyOf(byteArray, byteArray.length + 1); // the same as System.arraycopy()
}
public static void addByteToList1() {
// >>> SOLUTION TWO <<<
byteList.add(new Byte((byte) 0));
}
public static void testAddByteToList1() throws InterruptedException {
System.gc();
long m1 = getMemory();
long n1 = System.nanoTime();
for (int i = 0; i < 100000; i++) {
addByteToList1();
}
long n2 = System.nanoTime();
System.gc();
long m2 = getMemory();
byteList = new ArrayList<>();
nanoAvg.add(new Double(n2 - n1));
memAvg.add(new Double(m2 - m1));
}
public static void testAddByteToArray1() throws InterruptedException {
System.gc();
long m1 = getMemory();
long n1 = System.nanoTime();
for (int i = 0; i < 100000; i++) {
addByteToArray1();
}
long n2 = System.nanoTime();
System.gc();
long m2 = getMemory();
byteArray = new byte[0];
nanoAvg.add(new Double(n2 - n1));
memAvg.add(new Double(m2 - m1));
}
public static void resetMem() {
nanoAvg = new ArrayList<>();
memAvg = new ArrayList<>();
}
public static Double getAvg(List<Double> dl) {
double max = Collections.max(dl);
double min = Collections.min(dl);
double avg = 0;
boolean found = false;
for (Double aDouble : dl) {
if (aDouble < max && aDouble > min) {
if (avg == 0) {
avg = aDouble;
} else {
avg = (avg + aDouble) / 2d;
}
found = true;
}
}
if (!found) {
return getPopularElement(dl);
}
return avg;
}
public static double getPopularElement(List<Double> a) {
int count = 1, tempCount;
double popular = a.get(0);
double temp = 0;
for (int i = 0; i < (a.size() - 1); i++) {
temp = a.get(i);
tempCount = 0;
for (int j = 1; j < a.size(); j++) {
if (temp == a.get(j))
tempCount++;
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
return popular;
}
public static void testCompare() throws InterruptedException {
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 20; i++) {
testAddByteToArray1();
}
System.out.println("testAddByteToArray1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\tmemAvg:" + getAvg(memAvg).longValue());
resetMem();
for (int i = 0; i < 20; i++) {
testAddByteToList1();
}
System.out.println("testAddByteToList1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\t\tmemAvg:" + getAvg(memAvg).longValue());
resetMem();
}
}
private static long getMemory() {
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
}
public static void main(String[] args) throws InterruptedException {
testCompare();
}
}
You can try below solution inside some class:
int[] a = {10, 20, 30, 40, 50, 61};
// private visibility - or change it as needed
private void resizeArray(int newLength) {
a = Arrays.copyOf(a, a.length + newLength);
System.out.println("New length: " + a.length);
}
It is not possible to resize an array. However, it is possible change the size of an array through copying the original array to the newly sized one and keep the current elements. The array can also be reduced in size by removing an element and resizing.
import java.util.Arrays
public class ResizingArray {
public static void main(String[] args) {
String[] stringArray = new String[2] //A string array with 2 strings
stringArray[0] = "string1";
stringArray[1] = "string2";
// increase size and add string to array by copying to a temporary array
String[] tempStringArray = Arrays.copyOf(stringArray, stringArray.length + 1);
// Add in the new string
tempStringArray[2] = "string3";
// Copy temp array to original array
stringArray = tempStringArray;
// decrease size by removing certain string from array (string1 for example)
for(int i = 0; i < stringArray.length; i++) {
if(stringArray[i] == string1) {
stringArray[i] = stringArray[stringArray.length - 1];
// This replaces the string to be removed with the last string in the array
// When the array is resized by -1, The last string is removed
// Which is why we copied the last string to the position of the string we wanted to remove
String[] tempStringArray2 = Arrays.copyOf(arrayString, arrayString.length - 1);
// Set the original array to the new array
stringArray = tempStringArray2;
}
}
}
}
Sorry, but at this time is not possible resize arrays, and may be never will be.
So my recommendation, is to think more to find a solution that allow you get from the beginning of the process, the size of the arrays that you will requiere. This often will implicate that your code need a little more time (lines) to run, but you will save a lot of memory resources.
We can't do that using array datatype. Instead use a growable array which is arrayList in Java.

Resize an Array while keeping current elements in Java?

I have searched for a way to resize an array in Java, but I could not find ways of resizing the array while keeping the current elements.
I found for example code like int[] newImage = new int[newWidth];, but this deletes the elements stored before.
My code would basically do this: whenever a new element is added, the array largens by 1. I think this could be done with dynamic programming, but I'm, not sure how to implement it.
You can't resize an array in Java. You'd need to either:
Create a new array of the desired size, and copy the contents from the original array to the new array, using java.lang.System.arraycopy(...);
Use the java.util.ArrayList<T> class, which does this for you when you need to make the array bigger. It nicely encapsulates what you describe in your question.
Use java.util.Arrays.copyOf(...) methods which returns a bigger array, with the contents of the original array.
Not nice, but works:
int[] a = {1, 2, 3};
// make a one bigger
a = Arrays.copyOf(a, a.length + 1);
for (int i : a)
System.out.println(i);
as stated before, go with ArrayList
Here are a couple of ways to do it.
Method 1: System.arraycopy():
Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array. A subsequence of array components are copied from the source array referenced by src to the destination array referenced by dest. The number of components copied is equal to the length argument. The components at positions srcPos through srcPos+length-1 in the source array are copied into positions destPos through destPos+length-1, respectively, of the destination array.
Object[] originalArray = new Object[5];
Object[] largerArray = new Object[10];
System.arraycopy(originalArray, 0, largerArray, 0, originalArray.length);
Method 2: Arrays.copyOf():
Copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values. For any indices that are valid in the copy but not the original, the copy will contain null. Such indices will exist if and only if the specified length is greater than that of the original array. The resulting array is of exactly the same class as the original array.
Object[] originalArray = new Object[5];
Object[] largerArray = Arrays.copyOf(originalArray, 10);
Note that this method usually uses System.arraycopy() behind the scenes.
Method 3: ArrayList:
Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)
ArrayList functions similarly to an array, except it automatically expands when you add more elements than it can contain. It's backed by an array, and uses Arrays.copyOf.
ArrayList<Object> list = new ArrayList<>();
// This will add the element, resizing the ArrayList if necessary.
list.add(new Object());
You could just use ArrayList which does the job for you.
It is not possible to change the Array Size.
But you can copy the element of one array into another array by creating an Array of bigger size.
It is recommended to create Array of double size if Array is full and Reduce Array to halve if Array is one-half full
public class ResizingArrayStack1 {
private String[] s;
private int size = 0;
private int index = 0;
public void ResizingArrayStack1(int size) {
this.size = size;
s = new String[size];
}
public void push(String element) {
if (index == s.length) {
resize(2 * s.length);
}
s[index] = element;
index++;
}
private void resize(int capacity) {
String[] copy = new String[capacity];
for (int i = 0; i < s.length; i++) {
copy[i] = s[i];
s = copy;
}
}
public static void main(String[] args) {
ResizingArrayStack1 rs = new ResizingArrayStack1();
rs.push("a");
rs.push("b");
rs.push("c");
rs.push("d");
}
}
You could use a ArrayList instead of array. So that you can add n number of elements
List<Integer> myVar = new ArrayList<Integer>();
Standard class java.util.ArrayList is resizable array, growing when new elements added.
You can't resize an array, but you can redefine it keeping old values or use a java.util.List
Here follows two solutions but catch the performance differences running the code below
Java Lists are 450 times faster but 20 times heavier in memory!
testAddByteToArray1 nanoAvg:970355051 memAvg:100000
testAddByteToList1 nanoAvg:1923106 memAvg:2026856
testAddByteToArray1 nanoAvg:919582271 memAvg:100000
testAddByteToList1 nanoAvg:1922660 memAvg:2026856
testAddByteToArray1 nanoAvg:917727475 memAvg:100000
testAddByteToList1 nanoAvg:1904896 memAvg:2026856
testAddByteToArray1 nanoAvg:918483397 memAvg:100000
testAddByteToList1 nanoAvg:1907243 memAvg:2026856
import java.util.ArrayList;
import java.util.List;
public class Test {
public static byte[] byteArray = new byte[0];
public static List<Byte> byteList = new ArrayList<>();
public static List<Double> nanoAvg = new ArrayList<>();
public static List<Double> memAvg = new ArrayList<>();
public static void addByteToArray1() {
// >>> SOLUTION ONE <<<
byte[] a = new byte[byteArray.length + 1];
System.arraycopy(byteArray, 0, a, 0, byteArray.length);
byteArray = a;
//byteArray = Arrays.copyOf(byteArray, byteArray.length + 1); // the same as System.arraycopy()
}
public static void addByteToList1() {
// >>> SOLUTION TWO <<<
byteList.add(new Byte((byte) 0));
}
public static void testAddByteToList1() throws InterruptedException {
System.gc();
long m1 = getMemory();
long n1 = System.nanoTime();
for (int i = 0; i < 100000; i++) {
addByteToList1();
}
long n2 = System.nanoTime();
System.gc();
long m2 = getMemory();
byteList = new ArrayList<>();
nanoAvg.add(new Double(n2 - n1));
memAvg.add(new Double(m2 - m1));
}
public static void testAddByteToArray1() throws InterruptedException {
System.gc();
long m1 = getMemory();
long n1 = System.nanoTime();
for (int i = 0; i < 100000; i++) {
addByteToArray1();
}
long n2 = System.nanoTime();
System.gc();
long m2 = getMemory();
byteArray = new byte[0];
nanoAvg.add(new Double(n2 - n1));
memAvg.add(new Double(m2 - m1));
}
public static void resetMem() {
nanoAvg = new ArrayList<>();
memAvg = new ArrayList<>();
}
public static Double getAvg(List<Double> dl) {
double max = Collections.max(dl);
double min = Collections.min(dl);
double avg = 0;
boolean found = false;
for (Double aDouble : dl) {
if (aDouble < max && aDouble > min) {
if (avg == 0) {
avg = aDouble;
} else {
avg = (avg + aDouble) / 2d;
}
found = true;
}
}
if (!found) {
return getPopularElement(dl);
}
return avg;
}
public static double getPopularElement(List<Double> a) {
int count = 1, tempCount;
double popular = a.get(0);
double temp = 0;
for (int i = 0; i < (a.size() - 1); i++) {
temp = a.get(i);
tempCount = 0;
for (int j = 1; j < a.size(); j++) {
if (temp == a.get(j))
tempCount++;
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
return popular;
}
public static void testCompare() throws InterruptedException {
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 20; i++) {
testAddByteToArray1();
}
System.out.println("testAddByteToArray1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\tmemAvg:" + getAvg(memAvg).longValue());
resetMem();
for (int i = 0; i < 20; i++) {
testAddByteToList1();
}
System.out.println("testAddByteToList1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\t\tmemAvg:" + getAvg(memAvg).longValue());
resetMem();
}
}
private static long getMemory() {
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
}
public static void main(String[] args) throws InterruptedException {
testCompare();
}
}
You can try below solution inside some class:
int[] a = {10, 20, 30, 40, 50, 61};
// private visibility - or change it as needed
private void resizeArray(int newLength) {
a = Arrays.copyOf(a, a.length + newLength);
System.out.println("New length: " + a.length);
}
It is not possible to resize an array. However, it is possible change the size of an array through copying the original array to the newly sized one and keep the current elements. The array can also be reduced in size by removing an element and resizing.
import java.util.Arrays
public class ResizingArray {
public static void main(String[] args) {
String[] stringArray = new String[2] //A string array with 2 strings
stringArray[0] = "string1";
stringArray[1] = "string2";
// increase size and add string to array by copying to a temporary array
String[] tempStringArray = Arrays.copyOf(stringArray, stringArray.length + 1);
// Add in the new string
tempStringArray[2] = "string3";
// Copy temp array to original array
stringArray = tempStringArray;
// decrease size by removing certain string from array (string1 for example)
for(int i = 0; i < stringArray.length; i++) {
if(stringArray[i] == string1) {
stringArray[i] = stringArray[stringArray.length - 1];
// This replaces the string to be removed with the last string in the array
// When the array is resized by -1, The last string is removed
// Which is why we copied the last string to the position of the string we wanted to remove
String[] tempStringArray2 = Arrays.copyOf(arrayString, arrayString.length - 1);
// Set the original array to the new array
stringArray = tempStringArray2;
}
}
}
}
Sorry, but at this time is not possible resize arrays, and may be never will be.
So my recommendation, is to think more to find a solution that allow you get from the beginning of the process, the size of the arrays that you will requiere. This often will implicate that your code need a little more time (lines) to run, but you will save a lot of memory resources.
We can't do that using array datatype. Instead use a growable array which is arrayList in Java.

Traversal of an n-dimensional space

I'm trying to write an algorithm that will let me iterate over all desired points within an n-dimensional space to find the minimum of a function f(x) where x is a vector of size n.
Obviously, searching a 2-d or 3-d space is fairly straightforward, you can simply do:
for(int i = 0; i < x; i++) {
for(int j = 0; j < y; j++) {
//and so on for however many dimensions you want
Unfortunately, for my problem, the dimensionality of the space is not fixed (I'm writing a generalised minimum finder for many functions in a statistical program) and so I'd have to write loops for each value of n I want to use - which might ultimately be rather large.
I've been trying to get my head around how I could do this using recursion but can't quite see the solution - although I'm sure there is one there.
The solution doesn't have to be recursive, but it must be general and efficient (the inner most line in that nested loop is going to get called an awful lot...).
The way I'm representing the volume to search is a 2d array of double:
double[][] space = new double[2][4];
This would represent a 4d space with the minimum and maximum bound in each dimension in position 0 or 1 of the array, respectively. Eg:
dim 0 1 2 3
min(0):-10 5 10 -0.5
max(1): 10 55 99 0.2
Any ideas?
Here is the general idea:
interface Callback {
void visit(int[] p); // n-dimensional point
}
// bounds[] - each number the limits iteration on i'th axis from 0 to bounds[i]
// current - current dimension
// callback - point
void visit(int[] bounds, int currentDimension, int[] p, Callback c) {
for (int i = 0; i < bounds[currentDimension]; i++) {
p[currentDimension] = i;
if (currentDimension == p.length - 1) c.visit(p);
else visit(bounds, currentDimension + 1, p, c);
}
}
/// now visiting
visit(new int[] {10, 10, 10}, 0, new int[3], new Callback() {
public void visit(int[] p) {
System.out.println(Arrays.toString(p));
}
});
I'd stick with reucrsion, and use Object as a parameter, with an extra parameter of dim, and cast it when you reach a depth of 1 to the relevant array [in my example, it is an int[]]
public static int getMin(Object arr, int dim) {
int min = Integer.MAX_VALUE;
//stop clause, it is 1-dimensional array - finding a min is trivial
if (dim == 1) {
for (int x : ((int[])arr)) {
min = Math.min(min,x);
}
//else: find min among all elements in an array of one less dimenstion.
} else {
for (Object o : ((Object[])arr)) {
min = Math.min(min,getMin(o,dim-1));
}
}
return min;
}
example:
public static void main(String[] args) {
int[][][] arr = { { {5,4},{2}, {35} } , { {2, 1} , {0} } , {{1}}};
System.out.println(getMin(arr, 3));
}
will produce:
0
The advantage of this approach is no need for any processing of the array - you just send it as it is, and send the dimension as a parameter.
The downside - is type [un]safety, since we dynamically cast the Object to an array.
Another option is to iterate from 0 to x*y*z*... like you do when converting a number between binary and decimal representations. This is a non-recursive solution, so you won't run into performance issues.
ndims = n;
spacesize = product(vector_sizes)
int coords[n];
for (i = 0; i < spacesize; i++) {
k = i;
for (j = 0; j < ndims; j++ ) {
coords[j] = k % vector_sizes[j];
k /= vector_sizes[j];
}
// do something with this element / these coords
}
n-dimensional arrays can be flattened into one-dimensional arrays. What you need is to do the math for these things:
Calculate the size of the unidimensional array needed.
Figure out the formulas needed to translate back from the n-dimensional index to the unidimensional one.
This is what I'd do:
Represent n-dimensional array sizes and indexes as int[]. So, the size of a 5x7x13x4 4-dimensional array represented as the 4-element array `{ 5, 7, 13, 4 }'.
An n-dimensional array is represented as a unidimensional array whose size is the product of the sizes of each of the dimensions. So a 5x7x13x4 array would be represented as a flat array of size 1,820.
An n-dimensional index is translated into a unique index in the flat array by multiplication and addition. So, the index <3, 2, 6, 0> into the 5x7x13x4 array is translated as 3 + 2*5 + 6*5*7 + 0*5*7*13 == 223. To access that 4-dimensional index, access index 223 in the flat array.
You can also translate backwards from flat array indexes to n-dimensional indexes. I'll leave that one as an exercise (but it's basically doing n modulo calculations).
Isn't the function just:
Function loopDimension(int dimensionNumber)
If there is no more dimension, stop;
for(loop through this dimension){
loopDimension(dimensionNumber + 1);
}
This runs through a List of List of values (Integers) and picks the minimum of each List:
import java.util.*;
/**
MultiDimMin
#author Stefan Wagner
#date Fr 6. Apr 00:37:22 CEST 2012
*/
public class MultiDimMin
{
public static void main (String args[])
{
List <List <Integer>> values = new ArrayList <List <Integer>> ();
Random r = new Random ();
for (int i = 0; i < 5; ++i)
{
List<Integer> vals = new ArrayList <Integer> ();
for (int j = 0; j < 25; ++j)
{
vals.add (100 - r.nextInt (200));
}
values.add (vals);
}
showAll (values);
List<Integer> res = multiDimMin (values);
show (res);
}
public static int minof (List <Integer> in)
{
int res = in.get (0);
for (int v : in)
if (res > v) res = v;
return res;
}
public static List<Integer> multiDimMin (List <List <Integer>> in)
{
List<Integer> mins = new ArrayList <Integer> ();
for (List<Integer> li : in)
mins.add (minof (li));
return mins;
}
public static void showAll (List< List <Integer>> lili)
{
for (List <Integer> li : lili) {
show (li);
System.out.println ();
}
}
public static void show (List <Integer> li)
{
for (Integer i: li) {
System.out.print (" " + i);
}
System.out.println ();
}
}

Eliminating Recursion

I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.

Categories