Fluctuating array sizes - java

When I learned java, I was told that once created, the size of an array was fixed and couldn't be changed. Recently I've been using arrays a lot and have noticed that code similar to the following doesn't generate errors:
public class Test {
private static String[][] smallArray = new String[4][4];
private static String[][] biggerArray = new String[21][21];
private static String[][] assignedLater;
public static void main(String args[]){
for(int i = 0; i < smallArray.length; i++){
for(int j = 0; j < smallArray[0].length; j++){
smallArray[i][j] = i + j + "";
}
}
for(int i = 0; i < biggerArray.length; i++){
for(int j = 0; j < biggerArray[0].length; j++){
biggerArray[i][j] = i + j + "";
}
}
assignedLater = smallArray;
//last element of last row
System.out.println(assignedLater[3][3]) //returns 6
assignedLater = biggerArray;
//new last element of new last row
System.out.println(assignedLater[20][20]) //returns 40
}
}
After playing around with this for a bit, I ended up testing the following:
public class Test {
private static String[][] smallArray = new String[2][4];
private static String[][] biggerArray = new String[2][21];
private static String[][] errorArray = new String[3][21];
private static String[][] assignedLater = new String[2][0];
public static void main(String args[]){
//fill arrays as in previous example
assignedLater = smallArray;
//last element of last row
System.out.println(assignedLater[1][3]) //returns 6
assignedLater = biggerArray;
//new last element of new last row
System.out.println(assignedLater[1][20]) //returns 21
assignedLater = errorArray; //no error
System.out.println(assignedLater[2][20]); // returns 22
}
}
What's going on here?
Edit
Thanks for the responses, I am hereby enlightened as to why the impossible isn't actually happening.

You are not changing the size of arrays. You are just changing the reference to point to a different array in memory.

The arrays do not change size at all, what you are doing is making the varibles change reference, they will simply change which array they point to without those arrays changing size.

As Juned said you're just changing the reference so you don't need such a complicated example to demonstrate. Even this will suffice:
int[] smallArr = new int[5];
int[] bigArr = new int[5000];
smallArr = bigArr;
System.out.println(smallArr.length); // -> prints 5000...
but we still haven't changed the length of a static array, just changed the location to which smallArr refers to be where bigArr refers.

In your second block, when you have this line, you gave 'assignedLater' some dimensions:
private static String[][] assignedLater = new String[2][0];
But then, in your main function, you pointed it to different arrays, so the old dimensions no longer matter:
assignedLater = smallArray;
After this, any call to assignedLater indices will point to smallArray indices. (until you reassign it again later). And so on.

Related

array method issue in output [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
public class Test {
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
reverse(oldList);
for (int i = 0; i < oldList.length; i++)
System.out.print(oldList[i] + " ");
}
public static void reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++)
newList[i] = list[list.length - 1 - i];
list = newList;
}
}
how come the method does not apply and still get 1 2 3 4 5?
thank you !
This is happening because Java is pass by value. This means that when you pass an argument into a method you are passing the reference to it, not the argument itself. The changes that you make inside the method are resolved but in this case you don't return the modified argument. Try this simple experiment to see what I mean:
public static void main(String[] args) {
int x = 0;
foo(x);
System.out.println(x);
}
public static void foo(int x) {
x = 4;
}
This program will print 0 because the changes are essentially discarded. To return the copied reference try this:
public static int[] reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++) {
newList[i] = list[list.length - 1 - i];
}
return newList;
}
And in your main:
oldList = reverse(oldList);
A much more in depth answer:
Is Java "pass-by-reference" or "pass-by-value"?
There are couple of issues. You can fix it with below two Options:
Option 1:
1) Make a new copy of original array and use it as reference array to reverse
2) In reverse function, update values of array that has been passed in parameter and reverse it using reference array
public class Test {
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
reverse(oldList);
for (int i = 0; i < oldList.length; i++)
System.out.print(oldList[i] + " ");
}
public static void reverse(int[] list) {
// create a copy of initial array to use it to reverse
int[] newList = Arrays.copyOf(list,list.length);
for (int i = 0; i < list.length; i++)
// update original array and reverse it. Calling method still have reference to this array
list[i] = newList[list.length - 1 - i];
}
}
Console Output:
PS: Here the idea is to ensure the reference of array remains the same. You can do it using another array as reference array or using another local variable and swapping two values inside array or doing XOR between i and n-i-1 variable. There are n number of ways out of which 1 has been shared above.
Option 2:
1) No need to copy the reference of the old array to new array in reverse method
2) Return the new array reference back to the calling method
3) For above point you will also have to change the return type of reverse function
4) Save the new reference of array in a variable in the main method and then print from the same.
Please find my comments below:
public class Test {
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
//save the return list to a variable
int[] newList= reverse(oldList);
for (int i = 0; i < newList.length; i++)
//print the data from new list
System.out.print(newList[i] + " ");
}
// change the return type
public static int[] reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++)
newList[i] = list[list.length - 1 - i];
//remove this line as there is no point of copying old array back to new array
// list = newList;
//retrun newlist reference to the calling method
return newList;
}
}
Console Output:
This is happening because you are altering the new area, and the statement list = newList; does not affect the original list because java is pass by value and you only overwrite the pointer in the reverse function.
Instead you should return the new array and overwrite the old one like:
public class HelloWorld
{
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
oldList = reverse(oldList);
for (int i = 0; i < oldList.length; i++)
System.out.print(oldList[i] + " ");
}
public static int[] reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++)
newList[i] = list[list.length - 1 - i];
return newList;
}
}
Java is always pass-by-value. What does this mean for object- and array-references? In Java, we handle objects only through references. References live on the stack, the actual objects live on the heap. References store the address where the actual object resides.
If you pass an object to a method, the reference-value (i.e. the address where the object resides) is passed as parameter. For some method foo(Object o) this means: if you re-assign o in foo's body (e.g. through o = new Object();, this change will not be visible outside the method.
To fix you problem, you would either have to do the reversal in-place (i.e. on list directly) or return your newly created array. Here is an implementation of the in-place variant:
public static void reverse(final int[] values) {
final int length = values.length;
for (int i = 0; i < length / 2; ++i) {
final int j = length - i - 1;
swap(values, i, j);
}
}
public static void swap(final int[] values, final int i, final int j) {
int tmp = values[i];
values[i] = values[j];
values[j] = tmp;
}
For an implementation of the return-variant, look at one of the other answers since every other answer seems to implement a variant on this.
Some remarks on your code:
Giving an array-parameter the name list is confusing. A list is not the same as an array, the are different datastructures with differen properties.
You should never neglect the optional parentheses around one-line if-, else-, for-,... bodies. This can be the source of nasty bugs and is regarded as bad practice.
You should take a little bit more care wrt. your indentation. Keep in mind that your source code is a means of coummuncation. The more semantics you can transport through simple rules (like indentation), the easier it is to understand your source code.

filling values in array

what i want to do is fill the empty aray kyo[] with the add() method but it keeps getting an error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
0 at TestPlass.Add(TestPlass.java:30) at
TestPlass.main(TestPlass.java:18)
i'm just new to programming
public static int size = 30;
public static void main (String args[]) {
int kyo[] = {};
Add(kyo);
for(int x:kyo){
System.out.print(x + " ");
}
}
static void Add(int x[]){
for(int g=0; g<=size; g++){
x[g] = g;
}
}
If your kyo array has a fized size, you need to create it with this size.
public static int size = 30;
public static void main(String args[]) {
int kyo[] = new int[size];
add(kyo);
for (int x : kyo) {
System.out.print(x + " ");
}
}
static void add(int x[]) {
for (int g = 0; g < x.length; g++) {
x[g] = g;
}
}
You add function receives int x[] as input, so it should use x.length for the iterator and not your size variable.
I have also edited the name of your Add() method to be add() to respect Java code conventions.
An empty array can never have any content.
Once an array has been created, its size is fixed - you can change the content of the elements, but you can't change how many elements it has. See the Java arrays tutorial for more information.
If you need a dynamically-sized collection, I suggest you use a List<E> implementation, such as ArrayList<E>:
List<Integer> list = new ArrayList<>();
add(list);
for (int x : list) {
System.out.print(x + " ");
}
...
private static void add(List<Integer> list) {
// I assume you want "size" elements, not "size + 1"
for (int g = 0; g < size; g++) {
list.add(g);
}
}
This line:
int kyo[] = {};
creates an array of size zero. Arrays have a fixed size in Java; once an array has been created, its size is fixed. You have to create the array like this:
int[] kyo = new int[30];
This will create an array with 30 elements.
You need to give the size of the array when you create it, like:
int kyo[] = new int[size];
You can find some great info on arrays here:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Arrays do not resize themselves automatically, so the size you initialize it with will be its size forever.
Cheers,
Marcus
Your problem lies here: int kyo[] = {};
{} Creates an array of zero size. Since you are adding 31 elements to the array you need to initialize you array to appropriate size.
For example: int[] kyo = new int[31];

Shuffling elements in an Array (Java)

I need a shuffle method to shuffle elements of an array which holds objects from another class. At the moment I wrote this code to test with integers first, but it seems to not working perfectly. Most of the elements are being duplicated.
Can someone please spot the mistake?
And also come up with a more efficient method for this.
I am not sure if I can use collections.shuffle because I have further use of my shuffled array later.
public static void shuffle()
{
int[] a = new int[52];
int count = 0;
int random = 0;
while (count!=51){
random = (int)(Math.random() * 52);
for (int i=0; i <=count; i++){
if (a[count] != b[random])
result = true;
}
if (result){
a[count] = b[random];
count++;
}
b = Arrays.copyOf(a, a.length);
}
}
First you should not define shuffle() in this way. I would treat b as a parameter and pass it into shuffle() instead of a static field (as your shuffle() is declared as static, your b is also static right? It looks strange to share b between all instances), and result is declared as a local variable.
This part
for (int i=0; i <=count; i++){
if (a[count] != b[random])
result = true;
}
checks whether any one of a[0], a[1] until a[count] is not equal to b[random]. If yes, then assign b[random] to a[count] and increase count by 1. As a[] is not initialized, it is only an array of 0. (a[count] != b[random]) appears to be always true and hence result is true.
Then, for this part,
if (result){
a[count] = b[random];
count++;
}
say for example random=5, then at the first round of the while loop a[0]=b[5], count=1 (due to count++), and b becomes an array of b[5] and a series of 0. (Due to
b = Arrays.copyOf(a, a.length);
all other elements are replaced by 0.)
Edit: Here I provide a simple method, not thoroughly tested, but should work:
public static int[] shuffle(int[] array) {
int[] a = new int[array.length];
//convert int[] to ArrayList<Integer>
ArrayList<Integer> list = new ArrayList<>();
for (int i: array)
list.add(i);
//now shuffle:
for (int i=0; i<array.length; i++) {
int rand = (int)(Math.random()*list.size());
a[i] = list.remove(rand);
}
return a;
}
The array returned is shuffled. Actually I can't say the method "shuffles" the array. It simply creates an empty array, and repeatedly selects an element randomly and put it at the front.
Edit2: This really "shuffles", and this is another approach: does not return a new array. It shuffles the array, 100 times.
public static void shuffle(int[] array) {
for (int i=0; i<100; i++) {
int r1 = (int)(Math.random()*array.length);
int r2 = (int)(Math.random()*array.length);
int tmp = array[r1];
array[r1] = array[r2];
array[r2] = tmp;
}
}
import java.util.Random;
public class Shuffle {
public static void main(String[] args) {
Integer[] a = new Integer[52];
for (Integer i=0;i<a.length;i++) a[i] = i+1;
// Let's shuffle
Random rd = new Random();
for (Integer i=0;i<a.length;i++){
Integer changeBy = rd.nextInt(a.length);
Integer aux=a[i];
a[i]=a[changeBy];
a[changeBy] = aux;
}
// Now show the shuffled array
for (Integer i=0;i < a.length; i++) System.out.print(a[i]+",");
}
}
Hope this small algorithm helps you. As you can see from 2 different runs, it really shuffles your array:
11,1,24,13,28,15,25,48,5,22,12,32,29,42,34,7,33,31,47,18,51,40,8,17,41,20,6,36,21,45,27,52,38,10,30,14,23,19,43,4,50,46,44,3,49,37,35,2,9,26,16,39
3,10,37,26,41,15,28,52,6,24,20,43,33,21,51,32,25,40,50,8,7,5,4,35,13,16,49,17,29,47,12,14,36,39,45,30,2,42,23,38,31,19,27,46,34,11,18,1,22,48,9,44
Why no you HashSet for shuffle?
Elements in java.lang.HashSet are shuffling by their hashcode.
public static void shuffle()
{
int [] b; // you origin array
Set<Integer> temp = new HashSet<Integer>();
for (int i : b) {
temp.add(i);
}
Integer [] a = new Integer[b.length];
a = temp.toArray(a); // new shuffle array
}

Declaration of Array not accepted

I am creating a class that will play the role of a computer player in a virtual game of sticks. However, when I use the constructor method for this class, I lose the array that I have created, even though I had already declared the array in the state attributes. After 20 minutes, I am completely lost.
I am new to Java, and am trying to learn and get better. Any help would really be appreciated.
Below is the redesigned AI class along with the error that Eclipse keeps on submitting.
public class RedesignedAI {
private int[][] largeArray;
private int AIChoiceStick;
private Random random = new Random();
private int CurrentScore[] = new int[51]; //at max, if 100 sticks are initially chosen, then each player takes at max 50 sticks,
private int h = 0; //^so why not have one more in case
public RedesignedAI(int NumberSticks) //this is a constructor method and creates the arrays that contains a
{
largeArray[][] = new int[NumberSticks][3];
int i = 0;
while(i < NumberSticks)
{
largeArray[i][0] = 1; //ADD THIS
largeArray[i][1] = 1;
largeArray[i][2] = 1;
i++;
}
}
The error: largeArray cannot be resolved to a type.
You initialized the largeArraythe wrong way. Use:
largeArray = new int[NumberSticks][3];
That new allocate a 2D array, so types are coherent both sides of the =.
If you want to allocate chunk by chunk then you should use [] syntax:
largeArray = new int[NumberSticks][]; // array of NumberSticks entries to array of int (not yet determined)
for (int i=0; i<NumberSticks; i++) {
largeArray[i] = new int[3]; // i-th entry of array largeArray is a new array of 3 ints
}
largeArray is a reference to array of reference to array of ints. largeArray[i] is a reference to array of ints. largeArray[i][j]is an int.
Try this
private int[][] largeArray = null;
Initially initialize with null.
then in constructor
largeArray[][] = new int[3][3];
Since value is dynamic and you are changing it anyhow
You have to initialize the array on the top:
private int[][] largeArray = new int[x][y];
An array always has a fixed length. Only a list can variate the length.
Change this:
largeArray[][] = new int[NumberSticks][3];
into this:
largeArray = new int[NumberSticks][3];
Wrong Code:
largeArray[][] = new int[NumberSticks][3];
Instead use:
largeArray = new int[NumberSticks][3];
You don't need the [][] in the largeArray code of the constructor. This will do:
largeArray = new int[NumberSticks][3];
You may find it easier to use ArrayList instead. Maybe something like this:
private List<List<Integer>> largeArray;
...
public RedesignedAI(int NumberSticks) {
largeArray = new ArrayList<>();
int i = 0;
while(i < NumberSticks) {
List<Integer> innerArray = new ArrayList<>();
innerArray.add(1);
innerArray.add(1);
innerArray.add(1);
largeArray.add(innerArray);
i++;
}
}

ArrayList giving problems in java. positive integers solution to x+y+z+w = 13

So i am creating a method that basically gives all possible positive integer solutions to the problem x+y+z+w = 13. Really I have designed a program that can get all possible positive integer solutions to any number using any number of variables. I have managed to obtain the solution using this method:
public class Choose {
public static ArrayList<int[]> values;
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] loops = new int[3];
int q = 0;
values = new ArrayList<int[]>();
int[] array = new int[4];
System.out.println(choose(12,3));
NestedLoops(3,10,0,loops,13,array, 0);
for(int i = 0; i < values.size(); i++){
printArray(values.get(i));
}
}
public static void NestedLoops(int n, int k, int j,
int[] loops, int q, int[] array, int g){
if(j==n){
for(int i = 0; i< n; i++){
q-=loops[i];
}
if(q>0){
for(int i = 0; i < n; i++){
array[i] = loops[i];
}
array[n] = q;
values.add(array);
}
return;
}
for(int count = 1; count <= k; count++){
loops[j] = count;
NestedLoops(n,k,j+1,loops, 13, array, g);
}
}
}
My problem is that when i go to print the ArrayList, all i get is the last value repeated again and again. When i try to just print out the values instead of storing them in the ArrayList it works totally fine. This makes me think that the problem is with the values.add(array); line but i don't know how to fix it or what i am doing wrong. Thanks for any help offered.
Try using:
values.add(array.clone());
Every add of the same array just points to that array object. As you keep changing the same object, the final state is what is being shown for all stored elements. The print works as it just dumps the state of the array at that particular instant.

Categories