# java.util.ConcurrentModificationException tritt auf



## djafix (10. Jul 2014)

Hallo leute,

beim kopieren einer instanz einer klasse "Machine", welche mehrere referenzen (gesammelt in einer liste) auf elemente einer anderen klasse "ProductionOperation" besitzt, erscheint bei mir beim umschreiben der elemente eine java.util.ConcurrentModificationException. Jedoch habe ich doch eigentlich alle Modifikationen an den Listen extra außerhalb der foreach-schleife gelagert. hat vielleicht jemand eine idee woran das hier liegen könnte?


```
List<ProductionOperation> remove;
		List<Machine> machines = new ArrayList<Machine>();
		for (Machine m : problem.getMachines()) {
			Machine temp = new Machine(m);
			remove = new ArrayList<ProductionOperation>();
			for (ProductionOperation operation1 : m.getOperations()) {

				for (ProductionOperation operation2 : this.getOperations()) {
					if (operation1.getName() == "Q"
							|| operation1.getName() == "S") {
						remove.add(operation1);
						// m.getOperations().remove(operation1);
					}
					if (operation1.getName() == operation2.getName()) {
						temp.getOperations().add(operation2);
						// temp.getOperations().remove(operation1);
						remove.add(operation1);
						operation2.setMachine(temp);
					}
				}

			}
			temp.getOperations().removeAll(remove);
			machines.add(temp);
		}
		this.machines.addAll(machines);
```

das ist natürlich ein echt schwer zu verstehender algorithmus,aber falls jemand fragen dazu hat, kann ich die gerne beantworten. vielen dank schonmal für eure antworten


----------



## Phash (11. Jul 2014)

ich hoffe, name ist kein Objekt, sondern ein einfacher Datentyp... 
name impliziert aber eigentlich String (und du schreibst die Buchstaben in doppelte Hochkommas -> kein Char -> daher:
du müsstest wenn dann mit .equals() vergleichen - Stringvergleich.

Da du aber Referenzen vergleichst, kann das schon manchmal solche Blüten treiben

warum genau machst du eine new Machine(m)? Also warum machst du eine Maschine aus einer Maschine?
m ist doch genau die Maschine, die du willst


----------



## djafix (11. Jul 2014)

ok ich versuche es mal zu beschreiben...

ich habe eine klasse "Machine". in der befindet sich eine liste von "ProductionOrder". das einzige eindeutige attribut von ProductionOrder ist der String "name".  eventuell macht es hier sinn, die equls()-methode zu überschreiben?


```
Machine temp = new Machine(m)
```
 mache ich hier, weil ich zunächst die Liste aus der Orginal-Maschine in die neue Maschine bringe. Dann sind also die ProductionOrders aus dem Orginal-Problem in der neuen Maschine referenziert. 

Jetzt könnte man sich fragen, warum ich nicht gleich die einzelnen ProductionOrders in die Liste der neuen Maschine kopiere. Das liegt daran, dass diese bereits in "this" enthalten sind und nur noch zugeordnet werden müssen. 

Jedenfalls iteriere ich dann durch die Operationen der Orginalmaschine und prüfe zuerst ob der Name der Operation "Q" oder "S" ist,um die referenzen auf diese aus der neuen zu entfernen (zum verständnis: das sind dummy-operationen, die in meinem algorithmus für jede problem-instanz anhand ihrer restlichen operationen neu gesetzt werden. also haben die dort nixmehr verloren).

danach kommt also der namensvergleich. ich prüfe hier auf die gleichheit der namen der operation aus maschine m und aus "this". wenn der name gleich ist, wird die operation aus maschine m von temp entfernt und die operation aus "this" zu temp hinzugefügt. der operation aus "this" wird dann noch die maschine temp zugeordnet. 

ganz am ende werden dann die in einer liste gesammelten maschinen zur liste this.machines hinzugefügt.

ich glaube, die exception tritt auf, weil ich irgendwo etwas an einer liste änder, durch die ich gerade iteriere...ich weiß nur nicht wo?vielleicht findet ja jemand den fehler ???:L


----------



## VfL_Freak (11. Jul 2014)

Moin,



djafix hat gesagt.:


> ```
> if (operation1.getName() == "Q" || operation1.getName() == "S")
> ```


Da Dir "getname" einen String liefert, MUSST Du mit "_equals_" vergleichen !!:rtfm:
Also:

```
if (operation1.getName().equals("Q") || operation1.getName().equals("S") )
```

Gruß
Klaus


----------



## djafix (11. Jul 2014)

komisch,ich habe schon seit je her Strings mit == verglichen, und das hat auch immer funktioniert.
allerdings wenn man darüber nachdenkt, ist equals definitiv die richtige lösung..naja das ist ein anderes thema...

ich kann es zwar gerade nicht überprüfen, aber ich gehe fest davon aus dass die exception nicht aufgrund der stringvergleiche auftritt ..


----------



## VfL_Freak (11. Jul 2014)

Moin,

da Du innerhalb Deiner Schleifen relativ 'wild' rum änderst, kann das durch aus schon sein !
In welcher Zeile tritt die Exception denn überhaupt auf ?

Eventuell hilft Dir dies auch weiter (ziemlich am Ende) :
Galileo Computing :: Java ist auch eine Insel – 13.2 Mit einem Iterator durch die Daten wandern

Gruß
Klaus


----------



## Phash (11. Jul 2014)

schreib ich heute eigentlich irgendwie unsichtbar? oO

schrieb bereits oben, dass du Stings (wie alle Objekte) mit equals vergleichen musst (bei Strings gehts war häufig gut, weil Strings immutable sind, aber == ist nicht verlässlich)


----------



## VfL_Freak (11. Jul 2014)

Moin,



Phash hat gesagt.:


> schreib ich heute eigentlich irgendwie unsichtbar? oO


vermutlich :lol:



Phash hat gesagt.:


> schrieb bereits oben, dass du Stings (wie alle Objekte) mit equals vergleichen musst (bei Strings gehts war häufig gut, weil Strings immutable sind, aber == ist nicht verlässlich)


das '==' ist nicht nur _nicht verläßlich_ - es ist schlichtweg *falsch*, weil damit eben NICHT der Stringinhalt verglichen wird, sondern die Objektreferenz !!
http://www.java-forum.org/top-fragen/1350-vergleichen-strings.html
Java Blog Buch : 03.02 Strings vergleichen

Gruß
Klaus


----------



## Phash (11. Jul 2014)

das meinte ich damit  

muss mich mal stärker ausdrücken


----------



## djafix (11. Jul 2014)

ich kann das beides leider erst heute abend überprüfen. ich änder zuerst == zu equals() und dann guck ich nach in welcher zeile die exception geworfen wird.

bis dahin!


----------



## X5-599 (11. Jul 2014)

Also bei meinen Tests (seeehr Oberflächlich, da ich ja deine Fachklassen nicht kenne) fliegt die Exception in Zeile 6:

```
for (ProductionOperation operation1 : m.getOperations()) {
```

denn ich nehme an, dass das dieselbe Liste ist die in Zeile 15 verändert wird:

```
temp.getOperations().add(operation2);
```

vorrausgesetzt deine Machine Klasse sieht so ähnlich aus:

```
class Machine
{
	List<ProductionOperation> operations = new ArrayList<ProductionOperation>();
		
	Machine(Machine m)
	{
		this.operations = m.getOperations();
	}
		
	List<ProductionOperation> getOperations()
	{
		return operations;
	}
}
```

Da ich auch die genau Funktion nicht kenne, die du hier abbildest ist folgender Vorschlag mit Vorsicht zu genießen:


```
Machine(Machine m)
{
	this.operations = new ArrayList<ProductionOperation>();
	this.operations.addAll(m.getOperations());
}
```

Hier sollte eine neue (unabhängige) Listen Instanz erzeugt werden, die aber mit denselben ProductionOperation-Objekt Referenzen gefüllt ist.

Ich schreibe "sollte" da ich nicht genau weiß wie addAll genau funktioniert. Ich nehme an, die übergebene Liste wird durch-iteriert und die Objekte an die neue Liste angehängt. Es sollte also keine Abhängigkeit mehr zur alten Liste existieren.

Zumindest fliegt so bei meinen Tests keine Exception mehr. Ob aber das Resultat dem entspricht was du dir vorstellst wiess ich natürlich nicht.


----------



## stg (11. Jul 2014)

...oder er benutzt einfach einen Iterator, statt irgendwas mit irgendwelchen Hilfsliste zu frickeln. Dafür sind die schließlich da.


----------



## djafix (13. Jul 2014)

sooo...ich habe nun 1. die stringvergleiche von == auf equals() geändert...wie erwartet hat sich daraus keine änderung ergeben.... und 2. habe ich dann doch auf einen iterator zurückgegriffen,was mir dann doch als sinnvollste lösung erschien...und siehe da: es hat geklappt....

also danke an alle die mir geholfen haben!


----------

