ArrayIndexOutOfBoundsException in processing - java

So I've been working on a small tanks program, but whenever I try to run it I get an ArrayIndexOutOf BoundsException on line 477 (http://pastebin.com/k4WNXE6Q).
void placeStations(int Number) {
for (int i = 0; i<Number; i++) {
stations.add(new RefillStation(int(random(0, width)), int(random(0, height))));
// This line of code refuses to work. I get an 'ArrayIndexOutOfBoundsException: -3'
RefillStation station = stations.get(i);
for (Tank tank : tanks) {
if (station.getRectangle().intersects(tank.getRectangle())) {
station.kill();
i=i-1;
}
}
for (Obstacle obstacle : obstacles) {
if (station.getRectangle().intersects(obstacle.getRectangle())) {
station.kill();
i=i-1;
}
}
}
}
I have tried for hours to find an error, but I can see nothing different from the method above, which seems to work fine. I am using the 'i' type for loops in some places because whenever I try to remove something from an index in a modern for loop, it gives me a size change exception. Any Ideas on what I could do to remedy this?

Multiple overlaps with Tanks and Obstacles will cause i to be reduced repeatedly. But you want to kill the station only once: break out of the loop.
for (Tank tank : tanks) {
if (station.getRectangle().intersects(tank.getRectangle())) {
station.kill();
i=i-1;
break;
}
}

for(each) style loops use iterators under the hood and most of the time you can't edit a collection that you're iterating over other than through the remove() method of the iterator object. To do that you'll have to use the iterator explicitly. see this answer
btw variable names with an upper case first character work, but makes it harder for people to read and understand your code.

I am not sure if this is the issue but isn't ArrayList is supposed to have 1st argument for index and second one for the element:
public void add(int index,
E element)
And your code is :
stations.add(new RefillStation(int(random(0, width)), int(random(0, height))));
It is adding element first and then specifying the index.

Related

Including new elements in for:each

Before I start my question, i'd like to mention that i DID read up some other topics and i tried around a bit but im just really confused atm so i figured i'd just ask.
So what i wanna do is use for each through a Set and within that for each, add elements to that set and also iterate through those.
The solution I found elsewhere was the following:
for(Object obj : new HashSet<Object>(oldSet))
I tried that, however I keep missing some of the last elements i'd like to match so im not really sure if this is the right approach in the first place?
To be specific, this is basically what my code looks like:
for(Position pos : new HashSet<Position>(oldSet){
for(Delta delta : deltas){
if(board.getTokenAt(pos.plus(delta).equals(initial){
hitList.add(pos.plus(delta);
oldSet.add(pos.plus(delta);
}
}
oldSet.remove(pos);
}
Again, I'd just like to know if my approach is wrong or there must be an error elsewhere in my code so i know what to look at.
Thanks beforehand!
You can't really add to a data structure while iterating over it, that is almost guaranteed to have unexpected results.
However, there is a simple enough solution to your issue. Just process each item recursively when you find that it needs to be added, and add it to a separate List. At the end of iteration, add everything in the List to the main Set. This avoids the issue of adding during iteration while still allowing you to to process the newly added items.
It would look something like this:
List<Position> toAdd = new LinkedList<>();
for(Position pos : oldSet){
for(Delta delta : deltas){
addIfGoodAndRecurse(pos, delta, toAdd);
}
}
And then you can use this helper method to add the item if it meets your conditions and also recursively process added items. Note you will need to change the method signature to pass in your board, initial, and hitList if they are local variables. I didn't know their types or whether they were global variables or fields, so I couldn't really add them in the example.
private void addIfGoodAndRecurse(Position pos, Delta delta, List<Position> toAdd) {
Position toCheck = pos.plus(delta);
if(board.getTokenAt(toCheck.equals(initial))) {
hitList.add(toCheck);
toAdd.add(toCheck);
for (Delta recursionDelta : deltas) {
addIfGoodAndRecurse(toCheck, recursionDelta, toAdd);
}
}
}
I don't have your code, so I can't test this. The idea should work fine, but you may need to make slight modifications.
You can iterate through new elements added to a list that you're iterating if you add them to the end of the list and iterate through it using an index and the get() method, not through an Iterator. You can also use the Set as you are doing now, but only to make sure you only add unique items to your collection.
List<Position> list = new ArrayList<>(oldSet);
for (int i = 0; i < list.length; ++i) { // NB list.length could be different each time
Position pos = list.get(i);
for(Delta delta : deltas){
if(board.getTokenAt(pos.plus(delta).equals(initial){
hitList.add(pos.plus(delta));
if (oldSet.add(pos.plus(delta))) // Check if it already exists in the list
list.add(pos.plus(delta));
}
}
oldSet.remove(pos);
}

remotely remove item from arraylist after intersect

I am working on a game project. So far so good, but i just stuck on ome basic thing and i cant find a solution and make it work properly. I decided to come here and ask you ppl of suggestions.
PROBLEM:
When the player comes to contact with a diamond, i suppose to remove the diamond from the level and from the arraylist containing all the objects in the world. What always happens i get an exception error message after remove() method called.
CODES:
1.Class with the list: EDIT_1
private ArrayList<AbstractObject> objects = new ArrayList<AbstractObject>();
public void removeObject(String name){
ArrayList<AbstractObject> newest = new ArrayList<AbstractObject>();
ListIterator<AbstractObject> delete=objects.listIterator();
while(delete.hasNext()){
if(name.equals(delete.next().getName())){
delete.remove();
}
else{
delete.previous();
newest.add(delete.next());
}
}
objects=newest;
}
2.Player class calling the removeObject method: EDIT_1
public void playerLogic(){
fallingDown();
for(AbstractObject object : this.getWorld().getListOfObjects()){ <--------ERROR HERE
if(this.intersects(object)){
if(object instanceof FinishZone && points>=getWorld().getDiamondCount()){
if(!(getWorld().getManager().isMoreLevels())){
getWorld().getMenu().openMenu(true);
}
else{
this.getWorld().getManager().nextLevel();
}
}
if(object instanceof Diamond){
points++;
this.getWorld().removeObject(object.getName());
}
}
}
}
ERROR:
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at project.objects.characters.Player.playerLogic(Player.java:77)
at project.objects.characters.Player.update(Player.java:70)
at project.world.World.update(World.java:110)
at project.Main.update(Main.java:122)
at project.Main.run(Main.java:65)
at java.lang.Thread.run(Thread.java:745)
I checked up some examples of removing items from arraylist but i havent find the difference.
EDIT_1:
So i figured out how to do it but i always get the error. I edited the removeobject code block. This worked good with a neutral list that i created for testing. I put all the items which i dont want to delete into a new list than ovewritten the old arraylist with the newest one. It worked with no exception error. When i made the same with the game list i want to edit it thrown the same error.
Ill put there the render code too if maybe there is the problem...
public void render(Graphics g) {
if(menu.getChoice()==-1){
menu.render(g);
}
else if(menu.getChoice()==0){
g.setColor(Color.white);
for(AbstractObject tempObj : objects){
tempObj.render(g);
}
}
}
FIXED:
Ill changed the starting list is ListIterator instead of putting items in arrayList before adding it to ListIterator. All methods changed to iterate. Working fine :)
You can't remove object while iterating over a list.
One option - use iterator.remove() - if you iterate with iterator, not the "enhanced for loop". You'll need to slightly modify your loop code, but the functionality will be the same.
Another: Store all objects to remove in an auxiliary list, and remove them all at the end of the loop.

Monster object deletion

Short introduction:
I'm building a game, where monsters spawn at the top, and moves through a path, to the reach a point where they need to be removed/destroyed/deleted. But I can't seem to get the Monster Object deleted.
for (Monster i : Monstre)
{
this.add(i); //adds monster to JPanel
if(i.monstery > 50 && i.monsterx > 50){ //check if monster have reached end point
this.remove(i); //Should remove Object from the JPanel ?
i = null; //Sets object too null
Monstre.remove(i); //Removes object from arrayList "Monstre".
}else{
//Update the monsters bounds
The above removes the object from the JPanel, and it seems to be all good. But when i call System.out.println(Monstre.size()); I get an increasing amount of monsters spawned, and if increasing the monster spawn rate, the program starts to eventually slow down, because amount of monsters in the Monstre arraylist is over 9000, and never decreasing.
What I'm looking for, is a way to remove these objects while the game is running.
Remove the i = null; line. This is not C and you don't have to assign your variables to null. JVM will do that for you (google "java garbage collection"). Because of that line, you practically call Monstre.remove(null) which does not work.
Also, you cannot iterate over the collection in that manner and modify it (remove values). Save the monsters you want to delete in an array outside of the scope of the loop, and remove them after the loop finishes. Otherwise, use an iterator:
Iterator<Monster> it= Monstre.iterator();
while (it.hasNext()) {
Monster i= it.next();
//code code code
if (shouldDelete) {
this.remove(i);
it.remove();
}
}
In addition to the suggestion in the first answer, you should change your loop. Removing items from the Monstre list while using the for-each loop will cause problems.
Instead try :
Iterator<Monster> iter = Monstre.iterator ();
while (iter.hasNext())
{
i = iter.next();
this.add(i); //adds monster to JPanel
if(i.monstery > 50 && i.monsterx > 50){ //check if monster have reached end point
this.remove(i);
iter.remove();
}else{
EDIT :
Here's an explanation where you can't use the for-each loop :
So when should you use the for-each loop? Any time you can. It really
beautifies your code. Unfortunately, you cannot use it everywhere.
Consider, for example, the expurgate method. The program needs access
to the iterator in order to remove the current element. The for-each
loop hides the iterator, so you cannot call remove. Therefore, the
for-each loop is not usable for filtering. Similarly it is not usable
for loops where you need to replace elements in a list or array as you
traverse it. Finally, it is not usable for loops that must iterate
over multiple collections in parallel. These shortcomings were known
by the designers, who made a conscious decision to go with a clean,
simple construct that would cover the great majority of cases.
i = null; //Sets object too null
Monstre.remove(i); //Removes object from arrayList "Monstre".
Here you set the variable i to null then you request that i (i.e. null) is removed from your arraylist, the arraylist does not contain null so nothing happens. Setting things equal to null is very rarely nessissary.
As you have correctly said removing the i=null upsets the program, this is because you are iterating through the list and then changing the list while iterating, you have two options;
1) go through the Arraylist in a manor similar to an array
import java.util.*;
public class Test{
public static void main(String [] args){
ArrayList<Double> doubles=new ArrayList<Double>();
for(double i=0;i<10;i++){
doubles.add(i);
}
//remove 7.0s from doubles
for(int i=doubles.size()-1;i>=0;i--){
//must go through backwards - see http://stackoverflow.com/questions/12111210/java-arraylist-search-and-remove for why
if (doubles.get(i).equals(7.0)){
doubles.remove(i);
}
}
}
}
2) use an iterator and its remove method
import java.util.*;
public class Test{
public static void main(String [] args){
ArrayList<Double> doubles=new ArrayList<Double>();
for(double i=0;i<10;i++){
doubles.add(i);
}
//remove 7.0s from doubles
Iterator<Double> iterator=doubles.iterator();
while(iterator.hasNext()){
Double testDouble=iterator.next();
if (testDouble.equals(7.0)){
iterator.remove();
}
}
}
}
You cannot remove this element in a for-loop.
You need to use listIterator() method to retrieve an iterator that can be modified and loop with iterator-style. Otherwise you would always get java.util.ConcurrentModificationException

Remove all 10s in a list and append a same number of 0s to the list at the end in JAVA

I've done most part of this. Anyone give me a small hint about how do I find the number of 10s in the list.
Eg. Input would be
[10,4,6,10,6,7]
Output must be
[4,6,6,7,0,0]
import java.util.ArrayList;
import java.util.List;
public class prob64 {
public static List output;
public static void getVal(List ll)
{
int count=0;
List ll1=new ArrayList();
for(int i=0;i<ll.size();i++)
{
if((int)ll.get(i)!=10)
{
ll1.add(ll.get(i));
}
if((int)ll.get(i)==10)
{
count++;
}
}
if(count>0)
{
ll1.add(8);
}
output=ll1;
System.out.println(output);
}
public static void main(String[] args) {
List<Integer> ll=new ArrayList();
ll.add(10);
ll.add(1);
ll.add(10);
ll.add(2);
prob64.getVal(ll);
}
}
The current output I'm getting is [1,2,0]. I'm supposed to get [1,2,0,0]
List.remove(Object) removes the first matching element. It also returns a boolean indicating if a removal was really done, so this should work :
while(ll.remove(10)) {
ll.add(0);
}
That is, as long as you find 10s to remove, add 0s. Note that List.add adds the element at the end of the list, which is your requirement (if I'm correct).
I suppose this is some kind of learning exercise, but I would advise you to find better names for your variable (ll & ll1 does not make your function easy to read).
You are adding only one zero at the end of the loop (in case 10s were found). You should count the number of 10s then add zeros as much as this number. Your program should look something like this:
int count=0;
List ll1=new ArrayList();
for(int i=0;i<ll.size();i++)
{
if((int)ll.get(i)!=10)
ll1.add(ll.get(i));
else
count++;
}
for(int j=0; j<count;j++)
ll1.add(0);
If count is number of 10's to add, use:
for(int j=0; j<count;j++){
ll1.add(8); // or ll1.add(0); ???
}
Few points to add to what others have mentioned above
I don't see any reason why you must define the output List to be static. When you define something(variables/functions) as static they are owned by the class rather that the objects and also it is a good programming practice not to change them using instance functions.What I mean is if you wish only to print there is no need of that output instance variable. You can directly print ll1.
Please use Generics in your code. When you know all you have in your list are integers specify it - Even in the function getVal(). I don't know how your code is compiling but you cannot cast Object to an int.
(int)ll.get(i)!=10
This code will fail. Try using Integer instead of int.
Your problem statement read replacing all 10's with 0's. So why are you adding 8 instead.It must be
ll1.add(0);
As other have specifies you need to add 0 as many time as your count is. So another loop is needed. Rest all look good.

how do i use a hashmap keys to an array of strings?

im currently working on a multiple class assignment where i have to add a course based on whether the prerequisites exist within the program.
im storing my courses within the program class using a hashmap. (thought i would come in handy) however, im having a bit of trouble ensuring that these preReqs exist.
here is some code ive currently got going
public boolean checkForCourseFeasiblity(AbstractCourse c) throws ProgramException
{
AbstractCourse[] tempArray = new AbstractCourse[0];
tempArray= courses.keySet().toArray(tempArray);
String[] preReqsArray = new String[1];
preReqsArray = c.getPreReqs();
//gets all course values and stores them in tempArray
for(int i = 0; i < preReqsArray.length; i++)
{
if(courses.containsKey(preReqsArray[i]))
{
continue;
}
else if (!courses.containsKey(preReqsArray[i]))
{
throw new ProgramException("preReqs do not exist"); //?
}
}
return true;
}
ok so basically, tempArray is storing all the keySets inside the courses hashmap and i need to compare all of them with the preReqs (which is an array of Strings). if the preReqs exist within the keyset then add the course, if they dont do not add the course. return true if the course adds otherwise through me an exception. keep in mind my keysets are Strings e.g. a keyset value could be "Programming1" and the required prerquisite for a course could be "programming1". if this is the case add then add the course as the prereq course exists in the keyset.
i believe my error to be when i initialize mypreReqsArray with c.getPreReqs (note: getPreReqs is a getter with a return type String[]).
it would be really great if someone could aid me with my dilemma. ive tried to provide as much as possible, i feel like ive been going around in circles for the past 3 hours :(
-Thank you.
Try something like this, you don't need tempArray. The "for each" loop looks lots nicer too. If you want to throw an Exception I would put that logic in the place that calls this method.
public boolean checkForCourseFeasiblity(AbstractCourse c)
{
for(String each : c.getPreReqs())
{
if(! courses.containsKey(each))
{
return false;
}
}
return true;
}

Categories