remotely remove item from arraylist after intersect - java

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.

Related

ArrayIndexOutOfBoundsException in processing

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.

Removing Actors does not delet all Actors

I am currently trying to save special Actors so i can put them on a map again if the old map get loaded. Therefor i want to put them into a HashMap<String, ArrayList<Monster>> monsterAtMap and remove them from there Stages. So i am trying this:
private void saveMonsters() {
if (this.screen.figureStage.getActors().size == 0)
return;
ArrayList<Monster> monsters = new ArrayList<Monster>();
for (Actor a : this.screen.figureStage.getActors()) {
a.remove();
}
Gdx.app.log("Figurstage size", ""+ this.screen.figureStage.getActors().size);
this.monsterAtMap.put(this.currentMap.name, monsters);
}
As start. But i noticed that it does not delete all. It does just delete 10 thats all. I do log the size of it befor and after the deleting. It's current 21 (20Monsters and 1 Character) after delete the size is 11.I also added this this.screen.figureStage.getRoot().removeActor(a); but this does not change anything.
Any Idea to that?
[EDIT] I wrote a workaround so my idea is working but the general idea that should work isnt possible because the .remove() does not always delete the Actor in anyway?! The workaround does look like this:
private void saveMonsters() {
this.chara = this.screen.character;
if (this.screen.figureStage.getActors().size == 0)
return;
ArrayList<Monster> monsters = new ArrayList<Monster>();
for (Actor a : this.screen.figureStage.getActors()) {
if (a.getClass() == Monster.class)
monsters.add((Monster) a);
}
this.screen.figureStage.clear();
this.screen.figureStage.addActor(chara);
this.monsterAtMap.put(this.currentMap.name, monsters);
}
The .clear()does work correct.
Deleting objects from a container while iterating over that container is always fraught with issues and complications, and I think you're running into some of these issues with the Stage's list of actors. The Stage code tries to use SnapshotArray to hide some of these issues, but its not clear to me that it will work with the code you've written.
One way to avoid this would be to loop through getActors() once and copy the actors into the monsters array, then loop through the monsters array and remove the actors from the Stage (or invoke figureStage.getRoot().clearChildren()). This should prevent you from iterating over a list that you're modifying.
Alternatively, look at how Group.clearChildren() is implemented (it uses an explicit integer index in the array of children, and not an iterator over the Array, and avoid some of the issues).

Access arraylist from other class through foreach loop

I'm trying to access my ArrayList from my other class, through a Foreach-loop. But this doesn't seems to work, for some reason. No error, just simply won't execute the Foreach loop.
Heres my code:
for(Entity entity : world.entitys) {
if(entity.isMouseDown()) {
System.out.println("Touching Entity");
} else {
System.out.println("Is not Touching Entity");
}
}
Arraylist from World Class:
public ArrayList<Entity> entitys = new ArrayList<Entity>();
World is my other class. entitys is my Arraylist. Entity is my class for my entitys in the Arraylist.
If there is not compiler or runtime error thrown only reason per your description is that the ArrayList is empty...
Learn to debug, it will help you resolve this kind of problems without asking for anyone's help..

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;
}

Java Programming Error: java.util.ConcurrentModificationException

I'm writing a program as part of tutorial for a beginner Java student. I have the following method and whenever I run it, it gives me the following exception:
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Warehouse.receive(Warehouse.java:48)
at MainClass.main(MainClass.java:13)
Here's the method itself, within the class Warehouse:
public void receive(MusicMedia product, int quantity) {
if ( myCatalog.size() != 0) { // Checks if the catalog is empty
// if the catalog is NOT empty, it will run through looking to find
// similar products and add the new product if there are none
for (MusicMedia m : myCatalog) {
if ( !m.getSKU().equals(product.getSKU()) ) {
myCatalog.add(product);
}
}
} else { // if the catalog is empty, just add the product
myCatalog.add(product);
}
}
The problem seems to be with the if else statement. If I don't include the if else, then the program will run, although it won't work properly because the loop won't iterate through an empty ArrayList.
I've tried adding a product just to keep it from being empty in other parts of the code, but it still gives me the same error. Any ideas?
You can't be iterating through the same list you're going to add things to. Keep a separate list of the things you're going to add, then add them all at the end.
You must not modify mCatalog while you're iterating over it. You're adding an element to it in this loop:
for (MusicMedia m : myCatalog) {
if ( !m.getSKU().equals(product.getSKU()) ) {
myCatalog.add(product);
}
}
See ConcurrentModificationException and modCount in AbstractList.

Categories