5

Vorrei utilizzare un elenco collegato per eseguire estrazioni e inserimenti di elementi, provando tutte le combinazioni per un euristico. Gli elenchi collegati sono più efficienti per questo tipo di operazioni. Dal momento che vorrei provare tutte le possibili coppie di estrazioni/inserimenti, ho usato due diversi iteratori sull'elenco. Ciò solleva un "ConcurrentModificationException". Come posso eseguire questa operazione in modo efficiente, senza re-attraversare la lista ogni volta, in quanto ciò vanificherebbe l'intero scopo di utilizzare una lista in primo luogo?Come utilizzare due diversi iteratori su un elenco collegato in Java?

Ecco la parte rilevante del codice:

ListIterator<Integer> it1 = data.listIterator(); 
ListIterator<Integer> it2; 

while(it1.hasNext()) { 
    int i = it1.next(); 
    it2 = data.listIterator(); 

    while(it2.hasNext()) { 
     if (i == it2.next()) continue; // continue right away when the indexes are equal 
     it1.remove(); 
     it2.add(i); 
     if (length() < best) 
      return true; 
     } 

    // when the swap is not better/consistent 
    it2.remove(); 
    it1.add(i); 
} 
return false; 

Grazie

+2

Se si modifica l'elenco tramite un iteratore, non è possibile utilizzare altri iteratori. –

+1

È possibile utilizzare ConcurrentLinkedQueue perché non riceve CME? Sospetto che ci sia un modo più efficiente di fare qualsiasi cosa tu stia facendo in ogni caso. –

+0

Si prega di google tali: www.google.com/search?q=multi+dimensional+linked+list+java e controllare i risultati come http://www.dreamincode.net/forums/topic/282327-multi-dimensional-linked -list/ –

risposta

0

è possibile utilizzare qualsiasi numero di iteratori in un elenco quando si sta facendo solo un'operazione di lettura. Dato che stai facendo una rimozione/aggiunta qui, non puoi usare la stessa lista con due iteratori diversi perché causerà la ConcurrentModificationException come stai vivendo ora.

Cosa ti piace realizzare? Può essere, le persone possono aiutarti con diverse opzioni.

+1

Non si dovrebbero scrivere commenti come risposta. –

+0

concordato. Ma non mi consente di aggiungere un commento a causa dello stato iniziale in StackOverflow :(. – muruga

+0

A partire da due ore fa, non è più vero :) La soglia è 50. –

1

Non è possibile utilizzare più iteratori simultaneamente su un LinkedList, tuttavia è possibile con un CopyOnWriteArrayList

Prova questo:

List<Integer> safeData = new CopyOnWriteArrayList(date); 
// your code, but working with safeData rather than data 
+0

Grazie, ma questo è implementato come array, non come elenco. Ciò significa che gli inserti non saranno efficienti; O (n) invece di O (1). –

+1

@Le inserzioni di DavidBlinder saranno meno efficienti, ma non a causa di ciò che hai detto. liste * usa * matrici internamente, ma questa classe speciale ne fa una copia intera internamente al cambiamento per renderlo thread-safe - vedi javadoc collegato – Bohemian

1

Se ho ragione, si cerca una struttura di dati che offre diversi iteratori per manipolare la lista. Questo è tecnicamente difficile per l'originale java.util.LinkedList perché fa le pulizie per l'indice corrente e questo è possibile solo in modo efficiente se non ci sono cambiamenti paralleli nelle posizioni sconosciute nella lista da parte di altri iteratori. Tuttavia, puoi facilmente implementare una semplice LinkedList che non esegue questa operazione di manutenzione e supporta l'aggiunta/rimozione di più iteratori. Quindi, un iteratore non conosce la sua posizione nell'elenco, ma scommetto che non ti interessa. Basta usare qualcosa del genere:

public class MyList<T> { 
private MyNode<T> first = null, last = null; 

public MyNode<T> getFirst() { 
    return first; 
} 

public MyNode<T> getLast() { 
    return last; 
} 

public boolean contains(MyNode<T> n) { 
    return n.list == this; 
} 

/** 
* If beforeMe is null, toInsert is inserted at the end of the list. 
* @return inserted node 
*/ 
public void insertBefore(MyNode<T> beforeMe, MyNode<T> newNode) { 
    if (newNode == null) { 
     throw new IllegalArgumentException("toInsert must not be null!"); 
    } 

    if (newNode.list != null) { 
     throw new IllegalArgumentException("This node is already in the list " + newNode.list); 
    } 

    if (beforeMe == null) { 
     if (last == null) { 
      newNode.prev = newNode.next = null; 
      first = last = newNode; 
     } else { 
      last.next = newNode; 
      newNode.prev = last; 
      newNode.next = null; 
      last = newNode; 
     } 
    } else { 
     newNode.prev = beforeMe.prev; 
     newNode.next = beforeMe; 

     if (beforeMe.prev != null) { 
      beforeMe.prev.next = newNode; 
     } else { 
      first = newNode; 
     } 

     beforeMe.prev = newNode; 
    } 

    newNode.list = this; 
} 

/** 
* If beforeMe is null, t is inserted at the end of the list. 
* @return inserted node 
*/ 
public MyNode<T> insertBefore(MyNode<T> beforeMe, T t) { 
    MyNode<T> newNode = new MyNode<T>(t); 
    insertBefore(beforeMe, newNode); 
    return newNode; 
} 

public void remove(MyNode<T> n) { 
    if (n == null || n.list != this) { 
     throw new IllegalArgumentException("Node is not in the list!"); 
    } 

    if (n.prev != null) { 
     n.prev.next = n.next; 
    } else { 
     first = n.next; 
    } 

    if (n.next != null) { 
     n.next.prev = n.prev; 
    } else { 
     last = n.prev; 
    } 

    n.prev = n.next = null; 
    n.list = null; 
}} 

public class MyNode<T> { 

private T t; 
/** 
* written only by MyList 
*/ 
MyNode<T> prev = null; 
/** 
* written only by MyList 
*/ 
MyNode<T> next = null; 
/** 
* written only by MyList 
*/ 
MyList<T> list = null; 

public T get() { 
    return t; 
} 

public void set(T t) { 
    this.t = t; 
} 

public MyNode<T> previous() { 
    return prev; 
} 

public MyNode<T> next() { 
    return next; 
} 

public MyList<T> list() { 
    return list; 
} 

/** 
* called only by MyList. 
* @param t 
*/ 
MyNode(T t) { 
    this.t = t; 
}}