I am trying to make it so I can write data to a ArrayList to track random integers and then I will have a previous button that will go back to the last result (This is just testing that code this is not the full code for the project) I am getting an error when trying to take the int arraySize and subtract it by 1 and reprint the data. Any idea why this is happening or how another way to accomplish the task.
int lenth = 10;
ArrayList<Integer> list = new ArrayList<Integer>();
int arraySize = list.size();
Random random = new Random();
int newRandom = random.nextInt(lenth);
list.add(newRandom);
newRandom = random.nextInt(lenth);
list.add(newRandom);
System.out.println(list.get(arraySize));
arraySize--;
System.out.println(list.get(arraySize));
Also here is the error I am getting:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at test.C_MainActivity.main(C_MainActivity.java:22)
When you assign one primitive (such as an int) to another, this copies the value to the new variable. For objects, this works a bit differently in that these variables will point to the same object.
int arraySize = list.size();
So the above line will just set arraySize to the current size of the list, arraySize will not change as the list size changes. Since you do this when the list is empty, it will be and remain 0 and you'll try to get the elements at indices 0 and 0-1 = -1, which is where your exception comes in.
You should just set it after you've inserted all elements instead.
Note that indexing in Java starts at 0, so the last element will already be at list.size() - 1, not list.size().
You are setting arraySize before anything has been added to the list. The value of arraySize will always be 0 because you only set it at the beginning. When you call arraySize--, arraySize is now -1 and when you call list.get(arraySize), you will get an index out of bound exception as you are asking for index -1.
It seems like your goal is to enqueue values in a collection and then dequeue them. A LinkedList, for example, would be more appropriate with its push() and pop() methods.
Anyway you should not keep track of the ArrayList's size through an external variable. Such data is already provided for you inside ArrayList so you just have to query the list to know its size.
Related
I'm rather new to Java, and I'm trying to figure out a way to copy all primes inside of an array and copy those to another array.
To do so, I've implemented a separate isPrime() method to check whether the element is a prime, and another method that counts the number of primes in that array countPrimes(), such that I can determine the new array's size.
Here is where I'm kind of stuck:
public static int[] primesIn(int[] arr) {
int primeHolder = countPrimes(arr);
int[] copyArr = new int[primeHolder];
for (int i = 0; i < arr.length; i++) {
if (isPrime(arr[i]) == true) {
copyArr[>Needs to start from 0<] = arr[i];
}
}
return copyArr;
}
int[] arrayMan = {3,5,10,15,13};
At copyArr the position should be 0, followed by +1 everytime it finds a prime. If I were to give it i position, as in copyArr[i] = arr[i], then say the prime is at position 5, it would try to save the prime onto position 5of copyArr, which doesn't exist if there are only three primes in the original array, which would've given copyArr a length of only three.
Something tells me a different for loop, or maybe even an additional one would help, but I can't see how I should implement it. Help is greatly appreciated!
Have a second index variable int primeCount, and increment it whenever you find a prime. No need for a 2nd loop.
In modern days of abundant memory, things are usually not done like this. If you don't have some extra hard requirements, you could just use a resizable ArrayList<Integer>, and add() stuff in there. (and convert it back to int[] at the end if needed). This is also better in this case, because typically your countPrimes call will run much slower than ArrayList reallocations.
Read your words carefully:
At copyArr the position should be 0, followed by +1 everytime it
finds a prime.
That means that index in a new array does not depend on its position in the old array. Create a counter. And each time you place a prime number into a new array, increment it by 1. Thus you can always know where to put a new number.
I'm learning java and was told arrays are implemented as objects. But they show two different codes without diving into details.
First they ask us to use arrays like this, but the downside is to manually add the values:
int nums[] = new int[10];
nums[0] = 99;
nums[1] = -622;
.
.
.
Then they use this in some programs saying new is not needed because Java automatically does stuff:
int nums[] = {99, - 10, 100123, 18, - 972 ......}
If the second code is shorter and allows me to use arrays straightaway whats the point of the first code if they do the same thing but the first one require more code to input value by hand.
Let's say you were initializing an array of 1 million values, would you use the second method? No, because you would have a huge java file.
The first method is essentially allocating space:
int[] array = new int[1000000];
Creates 1 million spaces in memory with default value 0. Now if you want to initialize them, you may use a loop:
for (int i = 0; i < array.length; i++) {
array[i] = i;
}
If you wanted an array of 10 million values, you only change one number:
// Just add a 0 to 1000000
int[] array = new int[10000000]
Now, if the size of your array changes, you don't have to change the loop. But if you used the second method and wanted an array of 10 million values, you would have to add 9 million values, and 9 million commas to your java file - not scalable.
int[] array = {1, 2, 3, 4, ... 1000000};
The second method is not "scalable." It only works for small arrays where you can confidently assume that the default values of that array won't change. Otherwise, it makes A LOT more sense to use the first (more common) method.
//This is one way of declaring and initializing an array with a pre-defined size first
int nums[] = new int[10];
//This is initializing the array with a value at index 0
nums[0] = 99;
//This is initializing the array with a value at index 1 and likewise allocating rest of array index values
nums[1] = -622;
//This is another way of declaring and initializing an array directly with pre-defined values. Here if you see instead of declaring array size first, directly the values are initialized for it
int nums[] = {99, - 10, 100123, 18, - 972 ......}
It depends on the way you prefer to use the arrays, but you must remember that whenever you use "new" keyword, there is a new space or resource created every time in memory.
When you don't know the items of array at the time of array declaration, then prefer method-1,
and,
when you know the all the values of array at the time of array declaration, then go for method-2
Imagine you want to generate a series of random integers at runtime and want to store in the array:
int[] array = new int[1000000];
Random r = new Random();
for (int i = 0; i < array.length; i++)
array[i] = r.nextInt();
I'm making a program of the Card game War and I need the cards to not reappear so I used an Array list. I'm having trouble with this array list as it's supposed to be random and remove the number, but I get the error IndexOutOfBoundsException: Index 0, Size 0
List<Integer> values = new ArrayList<Integer>();
Random random = new Random();
Integer rand = random.nextInt(values.size()+1);
Integer cardId = values.get(rand);
values.remove(rand);
First add your Card(s) to your values List (e.g. probably not Integer).
What I'm saying is this, you need a deck of cards before you can play.
Your list is empty and you're
1) Trying to retrieve a value
2) Trying to remove a value
Which throws an error because the list is empty.
Sidenote: you can define rand and cardId as int, instead of Integer. Autoboxing/unboxing will take care of that for you.
Add values to your list and it will work as expected (and if you change random.nextInt(values.size()+1) to random.nextInt(values.size())).
You get this error because you try to access index 0 of an empty array, as it says. You cannot do this.
Your code has multiple issues.
You are not actually storing anything in values.
The acceptable range of indexes for .get() is 0 to size-1. The return range of random.nextInt(size+1) is 0 to size. This can produce out of range index values. Array indexes start at 0.
Provide the code for the values in the array...Or add values in the array.
You need to first give the List values before you can get values
List<Integer> values = new ArrayList<Integer>();
Random random = new Random();
Integer rand = random.nextInt(values.size()+1);
Try this to put values
for (int i = 1; i <= 52; i++){
values.add(i);
}
Integer rand = random.nextInt(values.size() + 1);
I have created a method to randomize the list:
public <T> List<T> randomize(List<T> list) {
LinkedList<T> randomizedList = new LinkedList<>();
Random random = new Random(list.size());
for (int i = random.nextInt(); i < list.size(); i++) {
randomizedList.add(list.get(i));
}
return randomizedList;
}
The list that I am passing to this method contains for e.g. five elements. When I am creating Random random = new Random(list.size()); I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.
But when I call random.nextInt(); instead of returning the number from the interval [0, 4] (which I expect to be returned) it returns me the value of for e.g.: -349120689. Which gives me an java.lang.IndexOutOfBoundsException: Index: -349120689, Size: 5.
Why is this happening and how to solve this?
new Random(list.size()); this sets the seed of the Random number generator to list.size(); I suggest changing to new Random() (which will give you a seed based on the current time of the system). Preferably though, you'd want to reuse the same Random object at all times.
random.nextInt(); here is where you'd want to put random.nextInt(list.size()); which will give you a number from 0 to list.size() - 1.
Even with the above changes, your code would just give you a sublist of the list starting at a random index and going until the end. Use Collections.shuffle(list) instead.
To do a real shuffling, you would need to "remember" which elements
you have inserted or not. In pseudo-code, you could do the
following:
Copy the original list to a new one, let's call it "orig"
Create a new, empty, list, let's call it "result"
As long as the orig list has elements, get an element at random index and add it to the result list. Remove the chosen element from orig list.
Return result list.
I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.
You've misunderstood the purpose of the Random(long) constructor. The purpose of that constructor is to specify a seed for the list. You don't want to do this - it would mean that every collection of size 5 is always shuffled the same way.
You specify the range on each call to nextInt. So if you want a random number between 0 (inclusive) and max (exclusive) you just use:
int value = random.nextInt(max);
However, it would be much better just to use Collections.shuffle instead of writing your own code to do this - assuming you really want a shuffle (which isn't what your current approach would give you anyway - even after fixing the nextInt call, you'd end up
with basically a sublist, because nextInt() is only called once. So if the first call to nextInt() returns 2 (in a list of 5) you'd end up returning a new list containing the final 3 elements. I strongly suspect that's not what you were trying to do.
As a side-note, when you want to know why an API isn't behaving the way you expect it to, read the documentation. The documentation of the Random(long) constructor and Random.nextInt() are pretty clearly not the behaviour you were expecting.
use this
public <T> List<T> randomize(List<T> list) {
LinkedList<T> randomizedList = new LinkedList<>();
Random random = new Random();
for (int i = random.nextInt(list.size()); i < list.size(); i++) {
randomizedList.add(list.get(i));
}
return randomizedList;
}
The argument to the Random constructor is a random seed, not the maximum of what it returns.
Pass the maximum number to nextInt() instead.
You're confusing the argument to nextInt(n) (upper bound for the randomization) with the argument to the constructor (random seed). You shoudl use nextInt(list.size), and probably, initialize the Random object using new Random().
Why does this cause an array out of bounds exception ?
x[10][2] = 5;
Should this be assigning the 3rd spot of the 11th array, the value 5
I thought of it in a rectangular way.
Its like we have to count 11 rows(representing the 10 arrays)
and then we have to go to the 3rd column that is the 2
OR
I should be looking at it as an array looking for the 11th spot in an array of size 2 that doesn't actually exist ?
Is the 11th element of x an array? If it is, what is its length?
You are receiving that error because it's likely the length of that element is less than 3.
Test it by trying
System.out.printf(x[10].length);
Hope that helps.
Why does this cause an array out of bounds exception?
x[10][2] = 5;
This only happens when you try to access a position out of the range that you had defined for your array. For example
int x[20][20];
You can make x[10][2] = 5; without a problem because 10 < 20 and 2 < 20. But if you did:
x[30][20] = 5;
You would have the out of bounds exception because you are trying to access the position (30,20) of the 2D array, a position that surpasses the size of the 2D array.
It is because x[10][2] does not exist.
It can be either because x[10] is not a valid element (i.e. x.length is equal to or greater than 10), or x[10][2] is not a valid element (i.e. x[10].length is equal to or greater than 2). The exception message tells you which index fails, if they differ.
Note that a multidimensional array doesn't have to be a matrix. This is called a jagged array.
For example, consider the following code (from Wikipedia):
int[][] arr = new int[2][]; // creates 2 rows
arr[0] = new int[3]; // 3 columns for row 0
arr[1] = new int[5]; // create 5 columns for row 1
Referencing arr[0][4] would throw an ArrayIndexOutOfBoundsException, while referencing arr[1][4] would not.
As Mark Stevens already mentioned in the comments, which one is the row and which one the column, is subjective. As opposed to what jazzbassrob says in the comments, Java has neither row-major nor column-major order. In fact, in Java, there is no such thing as a two-dimensional array, instead, it's actually an array of arrays.