3 votes

comment fonctionne String.equals()

J'ai essayé de comprendre le fonctionnement de certaines méthodes de l'API

Voici un extrait de la méthode equals de la classe java.lang.String

Quelqu'un peut-il me dire comment le code compare réellement deux chaînes de caractères. Je comprends la signification de count, mais que signifie offset. Comment ces variables obtiennent-elles des valeurs ?

Par exemple, lorsque je crée une chaîne, comment sont-elles initialisées ?

une description détaillée ligne par ligne et aussi comment et quand les variables d'instance, la valeur, le nombre, le décalage, etc. sont initialisés ?

 public boolean equals(Object anObject) {
  1014           if (this == anObject) {
  1015               return true;
  1016           }
  1017           if (anObject instanceof String) {
  1018               String anotherString = (String)anObject;
  1019               int n = count;
  1020               if (n == anotherString.count) {
  1021                   char v1[] = value;
  1022                   char v2[] = anotherString.value;
  1023                   int i = offset;
  1024                   int j = anotherString.offset;
  1025                   while (n-- != 0) {
  1026                       if (v1[i++] != v2[j++])
  1027                           return false;
  1028                   }
  1029                   return true;
  1030               }
  1031           }
  1032           return false;
  1033       }

9voto

RNJ Points 5820

Logiquement

while (n-- != 0) {
if (v1[i++] != v2[j++])
    return false;
}

est identique à

for (int i = 0; i < n; i++) {
    if (v1[i] != v2[j])
        return false;
    }
}

Je ne sais pas pourquoi les concepteurs de la JVM ont procédé de la sorte. Peut-être y a-t-il une amélioration des performances en utilisant une boucle while plutôt qu'une boucle for. Cela me semble assez proche du langage C, donc peut-être que la personne qui a écrit cela a une formation en C.

Offset est utilisé pour localiser le point de départ de la chaîne dans le tableau de caractères. En interne, les chaînes de caractères sont stockées sous forme de tableaux de caractères. Il s'agit de value

if (v1[i++] != v2[j++])
    return false;

vérifie les caractères dans le tableau de caractères sous-jacent de la chaîne.

et ligne par ligne, c'est

si la référence pointe vers le même objet, il faut utiliser la fonction "equals".

1014           if (this == anObject) {
1015               return true;
1016           }

si l'objet est une chaîne de caractères, vérifier qu'ils sont égaux

1017           if (anObject instanceof String) {

convertit le paramètre transmis en chaîne de caractères.

1018               String anotherString = (String)anObject;

se souvient de la longueur de this.string

1019               int n = count;

si les longueurs des deux chaînes correspondent

1020               if (n == anotherString.count) {

obtenir un tableau de caractères (la valeur est ce tableau)

1021                   char v1[] = value;
1022                   char v2[] = anotherString.value;

trouver où commence la chaîne de caractères dans ce tableau

1023                   int i = offset;
1024                   int j = anotherString.offset;

boucle sur un tableau de caractères. si les valeurs sont différentes, il faut renvoyer false

1025                   while (n-- != 0) {
1026                       if (v1[i++] != v2[j++])
1027                           return false;
1028                   }

tout le reste doit être vrai

1029                   return true;
1030               }
1031           }

s'ils ne sont pas de type String, ils ne peuvent pas être égaux

1032           return false;
1033       }

Pour comprendre les notions de décalage et de valeur, examinons la classe String

/** The value is used for character storage. */
private final char value[];

/** The offset is the first index of the storage that is used. */
private final int offset;

/** The count is the number of characters in the String. */
private final int count;

Les constructeurs initialisent ces variables. Le code du constructeur par défaut se trouve ci-dessous. Vous devriez voir quelque chose de similaire pour les autres constructeurs.

/**
  * Initializes a newly created {@code String} object so that it represents
  * an empty character sequence.  Note that use of this constructor is
  * unnecessary since Strings are immutable.
  */
 public String() {
    this.offset = 0;
    this.count = 0;
    this.value = new char[0];
 }

Le présent est un lien intéressant à consulter

0voto

Ankur Points 4371

Comme vous le savez peut-être, la gestion des chaînes de caractères en Java est un cas particulier, la plupart du temps la chaîne est assignée à partir des pools de chaînes de caractères, il se peut donc que pour un tableau de caractères "I am Learning Java" , une chaîne de référence renvoie à "I am Learning Java" , alors le décalage serait 0 d'autres chaînes peuvent pointer vers "am" Le décalage serait donc 2 . Comme certains codes natifs gèrent l'initialisation, je pense que l'offset est défini au cours de ce processus (pendant le partage de la mémoire à partir du pool de chaînes).

De plus, comme vous pouvez le voir dans le code

 public String(String original) {
         int size = original.count;
        char[] originalValue = original.value;
        char[] v;
        if (originalValue.length > size) {
            // The array representing the String is bigger than the new
          // String itself.  Perhaps this constructor is being called
            // in order to trim the baggage, so make a copy of the array.
           int off = original.offset;
          v = Arrays.copyOfRange(originalValue, off, off+size);
        } else {
           // The array representing the String is the same
          // size as the String, so no point in making a copy.
            v = originalValue;
       }
      this.offset = 0;
       this.count = size;
       this.value = v;
    }

Lorsqu'une nouvelle chaîne est créée à partir de l'ancienne, il se peut que l'ancienne chaîne (l'originale dans ce cas) provienne du pool de chaînes, c'est pourquoi un décalage est d'abord pris et ensuite le tableau entier est copié pour allouer de la nouvelle mémoire (la nouvelle chaîne ne partage pas la mémoire du pool de chaînes).

N'oubliez pas non plus que String est un type dérivé et que la chaîne est toujours stockée dans un tableau de caractères. Nous avons donc besoin d'un offset pour déterminer le point de départ de la chaîne dans le tableau de caractères.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X