View Full Version : [JAVA] Problemi con ArrayList
Andre31790
03-02-2012, 21:47
Ciao a tutti, devo correggere un programma in Java ma non ho ben capito l'errore che mi da nel main d'esempio:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at jbook.Account.accetto(Account.java:46)
at Esempio.main(Esempio.java:35)
L'errore viene segnalato in questa porzione di codice:
Collection<Utente> richieste = jane.richieste();
System.out.println("Ci sono " + richieste.size() + " richieste di amicizia per " + jane.getNome());
for(Utente richiedente : richieste){ // accetta tutte le richieste
jane.accetto(richiedente);
}
E ovviamente il codice del metodo accetto():
public void accetto(Utente nuovoAmico) throws RichiestaInesistenteException {
Boolean trovato = false;
for(Utente u : mio_utente.richieste() )
if(u.getNome().equals(nuovoAmico.getNome())) {
trovato = true;
mio_utente.addAmico(nuovoAmico);
mio_utente.delRichiesta(u);
}
if(!trovato) throw new RichiestaInesistenteException();
}
Cosa posso fare? Grazie mille!
Il problema è dovuto al fatto che vai a modificare la tua collection mentre la stai ciclando. Per risolvere dovresti utilizzare gli Iterator.
Esempio che crasha:
for(String message : messages) {
if (condition(message))
messages.remove(message);
}
Esempio che funziona:
for(Iterator<String> iter = messages.iterator(); iter.hasNext();) {
String message = iter.next();
if (condition(message))
iter.remove();
}
Snippet preso da: http://stackoverflow.com/a/841537/321354
Andre31790
04-02-2012, 08:05
Modificato in:
public void accetto(Utente nuovoAmico) throws RichiestaInesistenteException {
Boolean trovato = false;
for(Iterator<Utente> iter = mio_utente.richieste().iterator(); iter.hasNext(); ) {
Utente utente = (Utente) iter.next();
if(utente.getNome().equals(nuovoAmico.getNome())) {
trovato = true;
mio_utente.addAmico(nuovoAmico);
nuovoAmico.addAmico(mio_utente);
mio_utente.delRichiesta(utente);
}
}
if(!trovato) throw new RichiestaInesistenteException();
}
ma da un altro errore:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at jbook.Account.accetto(Account.java:48)
at Esempio.main(Esempio.java:35)
clockover
04-02-2012, 08:56
Non puoi usare un semplice iteratore per modificare gli elementi in una Collection... devi usare ListIterator e comunque non puoi modificare una lista direttamente dalla sua istanza, ma solo con il ListIterator
es
questo non va bene
ArrayList<Integer> al = new .....
ListIterator<Integer> li = al.listIterator();
while(li.hasNext()){
Integer in = li.next();
if(in.equals(5))
al.add(qualcosa);
}
questo va bene
ArrayList<Integer> al = new .....
ListIterator<Integer> li = al.listIterator();
while(li.hasNext()){
Integer in = li.next();
if(in.equals(5))
li.add(qualcosa);
}
Andre31790
04-02-2012, 11:16
Non puoi usare un semplice iteratore per modificare gli elementi in una Collection... devi usare ListIterator e comunque non puoi modificare una lista direttamente dalla sua istanza, ma solo con il ListIterator
es
questo non va bene
ArrayList<Integer> al = new .....
ListIterator<Integer> li = al.listIterator();
while(li.hasNext()){
Integer in = li.next();
if(in.equals(5))
al.add(qualcosa);
}
questo va bene
ArrayList<Integer> al = new .....
ListIterator<Integer> li = al.listIterator();
while(li.hasNext()){
Integer in = li.next();
if(in.equals(5))
li.add(qualcosa);
}
Sarà ma eclipse mi segnala errore se tento di fare quello che dici tu:
for(ListIterator<Utente> iter = mio_utente.richieste().listIterator(); iter.hasNext();)
Mi sono un po' distratto da questo errore, però la lista che voglio scorrere è il risultato di un metodo che restituisce una Collection.
Non puoi usare un semplice iteratore per modificare gli elementi in una Collection...
A me non risulta... prova questo codice:
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>() {
{
add("1");
add("2");
add("3");
}
};
for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
String string = iter.next();
if (string.equals("3"))
iter.remove();
}
for(String s: list){
System.out.println(s);
}
}
@Andre31790:
Se non chiami iterator.remove() è normale che ti da ancora (lo stesso) errore.
Andre31790
04-02-2012, 11:34
A me non risulta... prova questo codice:
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>() {
{
add("1");
add("2");
add("3");
}
};
for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
String string = iter.next();
if (string.equals("3"))
iter.remove();
}
for(String s: list){
System.out.println(s);
}
}
@Andre31790:
Se non chiami iterator.remove() è normale che ti da ancora (lo stesso) errore.
La rimozione la faccio tramite un metodo di un'altra classe poiché essendo gli attributi privati non posso accedere direttamente!
Inviato dal mio GT-I9100 usando Tapatalk
Ok, allora rifattorizziamo un attimo scomponendo il codice. Prima cerchi e poi rimuovi:
public void accetto(Utente nuovoAmico) throws RichiestaInesistenteException {
int index;
index = search(nuovoAmico);
if(index != -1){
mio_utente.addAmico(nuovoAmico);
mio_utente.delRichiesta(mio_utente.get(index));
}
else
throw new RichiestaInesistenteException();
}
private int search(Utente nuovoAmico){
int i=0;
for(Utente u : mio_utente.richieste() ){
if(u.getNome().equals(nuovoAmico.getNome())) {
return i;
}
i++;
}
return -1;
}
(Non so se esattamente quello che vuoi fare ma può essere una base di partenza).
Andre31790
04-02-2012, 12:20
Ok, allora rifattorizziamo un attimo scomponendo il codice. Prima cerchi e poi rimuovi:
public void accetto(Utente nuovoAmico) throws RichiestaInesistenteException {
int index;
index = search(nuovoAmico);
if(index != -1){
mio_utente.addAmico(nuovoAmico);
mio_utente.delRichiesta(mio_utente.get(index));
}
else
throw new RichiestaInesistenteException();
}
private int search(Utente nuovoAmico){
int i=0;
for(Utente u : mio_utente.richieste() ){
if(u.getNome().equals(nuovoAmico.getNome())) {
return i;
}
i++;
}
return -1;
}
(Non so se esattamente quello che vuoi fare ma può essere una base di partenza).
Ora provo a vedere se funziona. In sostanza, devo ricercare all'interno della Collection il nome utente che viene passato al metodo e "accettare la richiesta", quindi aggiungere il nome utente alla lista degli amici (addAmico()) e ovviamente rimuovere l'amico dalle richieste. Se funziona, devo solo aggiustrlo al mio codice modificando il meno possibile!
clockover
04-02-2012, 17:23
A me non risulta... prova questo codice:
for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
String string = iter.next();
if (string.equals("3"))
iter.remove();
}
Infatti anche tu hai usato un ListIterator
Andre31790
04-02-2012, 18:09
Ok, allora rifattorizziamo un attimo scomponendo il codice. Prima cerchi e poi rimuovi:
public void accetto(Utente nuovoAmico) throws RichiestaInesistenteException {
int index;
index = search(nuovoAmico);
if(index != -1){
mio_utente.addAmico(nuovoAmico);
mio_utente.delRichiesta(mio_utente.get(index));
}
else
throw new RichiestaInesistenteException();
}
private int search(Utente nuovoAmico){
int i=0;
for(Utente u : mio_utente.richieste() ){
if(u.getNome().equals(nuovoAmico.getNome())) {
return i;
}
i++;
}
return -1;
}
(Non so se esattamente quello che vuoi fare ma può essere una base di partenza).
Inseriti tutti e due i metodi però mi segnala ora questo errore:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at Esempio.main(Esempio.java:34)
clockover
04-02-2012, 18:20
Inseriti tutti e due i metodi però mi segnala ora questo errore:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at Esempio.main(Esempio.java:34)
Ma sei proprio sicuro che quell'eccezione si riferisca a quella porzione di codice??
Andre31790
04-02-2012, 19:12
Ma sei proprio sicuro che quell'eccezione si riferisca a quella porzione di codice??
Si riferisce a questa porzione di codice:
for(Utente richiedente : richieste){ // accetta tutte le richieste
jane.accetto(richiedente);
Se è sbagliato vuol dire che Eclipse è impazzito!
clockover
04-02-2012, 20:44
Precisiamo una cosa.. Eclipse non c'entra nulla con le eccezioni
Quell'eccezione è scatenata da un'operazione di modifica di una struttura dati che viene scandita da un iteratore. Quindi morale della favola devi usare un ListIterator.
Comunque dato che stai utilizzando un ArrayList perchè non operarci direttamente senza iteratore?? Praticamente la usi come un semplice array, solo che in questo caso è dinamico.
Hai necessità di prestazioni elevate? Cioè la tua ArrayList è molto grande?
Andre31790
04-02-2012, 22:04
Precisiamo una cosa.. Eclipse non c'entra nulla con le eccezioni
Quell'eccezione è scatenata da un'operazione di modifica di una struttura dati che viene scandita da un iteratore. Quindi morale della favola devi usare un ListIterator.
Comunque dato che stai utilizzando un ArrayList perchè non operarci direttamente senza iteratore?? Praticamente la usi come un semplice array, solo che in questo caso è dinamico.
Hai necessità di prestazioni elevate? Cioè la tua ArrayList è molto grande?
Con o senza iterator da errore. Per il main d'esempio la lista contiene pochi elementi, però essendo una prova che devo consegnare deve prwvedere anche una lista con un po' più elementi!
Inviato dal mio GT-I9100 usando Tapatalk
clockover
04-02-2012, 22:22
Tutte le porzioni di codice che hai postato tu però usavano un iteratore. Io e CwNd ti abbiamo mostrato come usare un ListIterator
Modifica con ListIterator e facci sapere
Andre31790
05-02-2012, 08:17
Tutte le porzioni di codice che hai postato tu però usavano un iteratore. Io e CwNd ti abbiamo mostrato come usare un ListIterator
Modifica con ListIterator e facci sapere
L'avevo già scritto in un post precedente: se definisco l'oggetto come ListIterator non mi fa inserire il metodo listIterator() (come codice intendo) per la collection che interessa a me!
Inviato dal mio GT-I9100 usando Tapatalk
Andre31790
05-02-2012, 12:42
Modificando solo il metodo search() così:
public int search (Utente utente) {
int i = 0;
Iterator<Utente> li = mio_utente.richieste().iterator();
while(li.hasNext()){
Utente u = li.next();
if(u.getNome().equals(utente.getNome()))
return i;
i++;
}
return -1;
}
ottengo sempre questo errore:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at Esempio.main(Esempio.java:34)
Se provo ad utilizzare il maledetto ListIterator così:
ListIterator<Utente> li = mio_utente.richieste().listIterator();
mi segnala che il metodo listiterator() non è definito per il tipo Collection<Utente>
Ma richieste() che tipo restituisce?? listIterator() lo devi invocare su una classe che implementa List o che eredita da AbstractList.
Andre31790
05-02-2012, 13:34
Ma richieste() che tipo restituisce?? listIterator() lo devi invocare su una classe che implementa List o che eredita da AbstractList.
Restituisce una Collection
Inviato dal mio GT-I9100 usando Tapatalk
Prova qualcosa del genere
ListIterator<Utente> li = new ArrayList(mio_utente.richieste()).listIterator();
Non capisco molto bene la situazione. Ci sarebbe da aggiungere il tipo ad ArrayList.
Andre31790
05-02-2012, 16:00
Prova qualcosa del genere
ListIterator<Utente> li = new ArrayList(mio_utente.richieste()).listIterator();
Non capisco molto bene la situazione. Ci sarebbe da aggiungere il tipo ad ArrayList.
Il metodo richieste restituisce una Collection salvata all'interno di un'altra classe (poi sarebbe un array list però ovviamente la vrde come una collection)
Appena ho un minuto provo a fare così e faccio sapere!
Inviato dal mio GT-I9100 usando Tapatalk
Se posti tutto il codice cerco di darti un aiuto più concreto.
Andre31790
05-02-2012, 18:41
E' un po' lungo però ti posto solo quelli che interessano:
- Classe ACCOUNT:
public class Account {
private String nome_utente;
private String password;
private Utente mio_utente;
public Account (String id,String pwd) {
nome_utente=id;
password=pwd;
String nomeReale = null;
Utente u = new Utente(nomeReale);
mio_utente = u;
}
public void accetto(Utente nuovoAmico) throws RichiestaInesistenteException {
int index = search (nuovoAmico);
if(index!=-1){
mio_utente.addAmico(nuovoAmico);
mio_utente.delRichiesta(nuovoAmico);
nuovoAmico.addAmico(mio_utente);
}
else throw new RichiestaInesistenteException();
}
public int search (Utente utente) {
int i = 0;
Iterator<Utente> li = mio_utente.richieste().iterator();
while(li.hasNext()){
Utente u = li.next();
if(u.getNome().equals(utente.getNome()))
return i;
i++;
}
return -1;
}
- Classe Utente:
public class Utente {
private String nome_reale;
private List<Utente> richieste = new ArrayList<Utente>();
private List<Utente> amicizie = new ArrayList<Utente>();
private List<Messaggio> bacheca = new ArrayList<Messaggio>();
public Utente (String nReale) {
nome_reale = nReale;
}
public Collection<Utente> richieste(){
return richieste;
}
public void delRichiesta (Utente u) {
richieste.remove(u);
}
public void addAmico (Utente u) {
amicizie.add(u);
}
Se preferisci ti posso mandare tutto il progetto via email
Se fai restituire a richieste() un List<Utente> dovresti risolvere. Questa linea dovrebbe funzionare
ListIterator<Utente> li = mio_utente.richieste().listIterator();
Sta tutto a vedere se una List<Utente> ti può andare bene o ti limita molto rispetto ad una Collection<Utente>. Qualche esperto che ci può illuminare?
Andre31790
05-02-2012, 19:06
Se fai restituire a richieste() un List<Utente> dovresti risolvere. Questa linea dovrebbe funzionare
ListIterator<Utente> li = mio_utente.richieste().listIterator();
Sta tutto a vedere se una List<Utente> ti può andare bene o ti limita molto rispetto ad una Collection<Utente>. Qualche esperto che ci può illuminare?
Purtroppo il metodo deve restituire una Collection! E' una richiesta del compito.
Allora prova come ti ho detto passando la collection al costruttore di ArrayList ;)
Andre31790
06-02-2012, 18:42
Allora prova come ti ho detto passando la collection al costruttore di ArrayList ;)
Provato ma viene lanciata sempre la stessa eccezione!
Andre31790
16-02-2012, 19:26
Non ho più detto nulla, ma ho risolto utilizzando l'iterator per scorrere la lista che ho spostato nella stessa classe del metodo che lanciava l'eccezione.
Grazie mille per l'aiuto a tutti!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.