Question

    

Cette question a déjà une réponse ici:

    
            
  •              >                                      7 réponses                          
  •     
    

D'accord, je vais donc parcourir une liste de tableaux et supprimer un élément spécifique. Cependant, j'ai quelques difficultés à utiliser la structure de type For-Each. Quand je lance le code suivant:

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for(String t : arr)
{
  t = " some other value "; //hoping this would change the actual array
}

for(String t : arr)
{
  System.out.println(t); //however, I still get the same array here
}

Ma question est la suivante: comment puis-je faire en 't' un pointeur sur 'arr' afin de pouvoir modifier les valeurs dans une boucle for-each? Je sais que je pourrais faire une boucle dans ArrayList en utilisant une structure différente, mais celle-ci a l’air si nette et lisible que ce serait bien de pouvoir créer un pointeur.

Tous les commentaires sont appréciés! Même si vous dites que je devrais juste le sucer et utiliser une construction différente.

Était-ce utile?

La solution

Je pense que la meilleure approche peut être d'utiliser une boucle for.

    ArrayList<String> arr = new ArrayList<String>();

    for (int i = 0; i < arr.size(); i++) {

        String t = arr.get(i);

        if (// your condition is met) {
            arr.set(i, "your new value");
        }
    }

Autres conseils

Le problème est que vous essayez de modifier la référence t à la portée d'une boucle afin qu'elle pointe vers une nouvelle instance de chaîne. Ça ne va pas marcher. Il ne fait pas référence à l'entrée réelle dans la liste. Vous devez modifier la valeur actuelle de la référence. Si String était modifiable et fournissait une méthode fictive set () , vous pourriez en théorie faire

for (String t : arr) {
    t.set("some other value");
}

ou alors, mais ce n'est pas possible car c'est immuable. Il est préférable d’obtenir une poignée du point d’entrée dans le tableau lui-même en utilisant la boucle normale pour :

for (int i = 0; i < arr.size(); i++) {
    arr.set(i, "some other value");
}

Si vous insistez pour utiliser la boucle améliorée pour , vous devez remplacer String par StringBuilder , qui est modifiable:

for (StringBuilder t : arr) {
     t.delete(0, t.length()).append("some other value");
}

N'oubliez pas que Java est valeur par passe, pas par référence.

Pour-chacun ne vous donne pas un pointeur d'index, vous ne pouvez donc pas l'utiliser pour changer une valeur immuable.

Utilisez une boucle for avec un index ou utilisez un type mutable (comme StringBuffer, pas String)

Un tableau d'objets (comme des chaînes) en Java est un bloc contigu contenant une série ordonnée de références. Ainsi, lorsque vous avez un tableau de 4 chaînes, vous avez en réalité 4 références stockées DANS le tableau et 4 objets chaîne qui sont en dehors du tableau mais qui sont référencés par ses 4 éléments.

La structure for-each de Java crée une variable locale et, pour chaque itération, copie dans cette variable locale la référence de la cellule du tableau qui correspond à cette itération. Lorsque vous définissez la variable de boucle ( t = "une autre valeur" ), vous insérez une référence dans une nouvelle chaîne, "une autre valeur" , dans le répertoire local. variable t, pas dans le tableau.

Les contrastes avec d'autres langages (comme Perl) où la variable de boucle se comporte comme un alias de l'élément tableau / liste lui-même.

Votre code est réécrit par le compilateur comme suit:

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for (final Iterator <String> i = arr.iterator(); i.hasNext();) {
    String t;

    t = i.next();
    t = " some other value "; // just changes where t is pointing
}

Pour faire ce que vous voulez, vous devez écrire la boucle for comme ceci:

for (final ListIterator<String> i = arr.iterator(); i.hasNext();) {
     final String t;

     t = i.next();
     i.set("some other value");
}

Iterator n'a pas la méthode set, seulement ListIterator en a.

En gros, vous voulez supprimer la chaîne t de la liste arr. Faites juste un arr.remove (t) et vous pourriez être fait. Mais vous ne pouvez pas le faire en parcourant la même liste. Vous obtiendrez une exception si vous essayez de modifier la liste de cette façon.

Vous avez deux options:

  1. clonez votre liste, parcourez le clone et supprimez la chaîne "spécifique" de la liste d'origine
  2. créez une liste pour supprimer les candidats, ajoutez toutes les chaînes "spécifiques" à cette liste et, après avoir parcouru la liste d'origine, parcourez la corbeille et supprimez tout ce que vous avez collecté ici de la liste d'origine.

L'option 1 est l'easist, le clone peut être fait comme:

List<String> clone = new ArrayList<String>(arr);

Vous semblez mal comprendre le fonctionnement des objets / références en Java, ce qui est fondamental pour utiliser efficacement le langage. Cependant, ce code devrait faire ce que vous voulez (excuses pour le manque d’explication):

ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)

for(int i = 0; i < arr.size(); i++)
{
  arr.set(i, " some other value "); // change the contents of the array
}

for(String t : arr)
{
  System.out.println(t); 
}

Je crois que cela n’est pas lié à l’immuable ou au mutable.

 t = " some other value "; //hoping this would change the actual array

t ne contient pas la référence à un objet réel. Java copie la valeur de arraylist et la met dans t afin que la valeur de la liste ne soit pas affectée.

HTH

Cela a été bien répondu. Voici encore ma suggestion. La boucle à l'intérieur n'est pas visible. Il ne sera pas vu en dehors de la boucle. Vous pourriez faire t.set () s'il ne s'agissait pas de String .

Utilisez un StringBuffer plutôt que des chaînes en clair. De cette façon, la chaîne à l'intérieur est mutable.

Les chaînes sont immuables. Si vous avez un type mutable tel que StringBuilder / Buffer, vous pouvez modifier la chaîne dans votre itération. Vous avez des références, rappelez-vous.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top