193 votes

Pourquoi ajouter "" pour une Chaîne économiser de la mémoire?

J'ai utilisé une variable avec un grand nombre de données, dire String data. Je voulais utiliser une petite partie de cette chaîne de la façon suivante:

this.smallpart = data.substring(12,18);

Après quelques heures de débogage (avec une mémoire visualizer) j'ai découvert que les objets champ smallpart retenu toutes les données à partir d' data, bien qu'il ne contient la sous-chaîne.

Quand j'ai changé le code:

this.smallpart = data.substring(12,18)+""; 

..le problème a été résolu! Maintenant, mon application utilise très peu de mémoire maintenant!

Comment est-ce possible? Quelqu'un peut-il expliquer cela? Je pense que c'.smallpart gardé le référencement vers les données, mais pourquoi?

Mise à JOUR: Comment puis-je effacer la grosse Corde, alors? Data = new String(des données.substring(0,100)) faire la chose?

159voto

Brian Agnew Points 143181

Procédant de la manière suivante:

data.substring(x, y) + ""

crée un nouveau (petit) Chaîne de caractères de l'objet, et jette la référence à la Chaîne créée par substring(), permettant ainsi la collecte des ordures.

La chose importante à réaliser est que l' substring() donne une fenêtre sur un existant Chaîne - ou plutôt, le tableau de caractères sous-jacente de la Chaîne d'origine. Par conséquent, il consommera la même mémoire que la Chaîne d'origine. Cela peut être avantageux dans certaines circonstances, mais un problème si vous souhaitez obtenir une sous-chaîne et de les éliminer de la Chaîne d'origine (comme vous l'avez trouvé).

Jetez un oeil à la méthode substring() dans le JDK Chaîne source pour plus d'info.

EDIT: pour répondre À votre question supplémentaire, la construction d'une nouvelle Chaîne de la sous-chaîne permettra de réduire votre consommation de mémoire, à condition que vous bin toute référence à la Chaîne d'origine.

NOTE (Jan 2013). Le ci-dessus comportement a changé en Java 7u6. Le poids mouche modèle n'est plus utilisé et substring() va travailler comme vous le souhaitez.

28voto

Pascal Thivent Points 295221

Si vous regardez le code source de l' substring(int, int), vous verrez qu'il retourne:

new String(offset + beginIndex, endIndex - beginIndex, value);

value est à l'origine d' char[]. Ainsi, vous obtenez une nouvelle Chaîne, mais avec le même sous-jacent char[].

Lorsque vous le faites, data.substring() + "", vous obtenez une nouvelle Chaîne avec un nouveau sous-jacents char[].

En fait, votre cas d'utilisation est la seule situation où vous devez utiliser l' String(String) constructeur de:

String tiny = new String(huge.substring(12,18));

17voto

Chris Jester-Young Points 102876

Lorsque vous utilisez substring, il ne fait pas de créer une nouvelle chaîne. Il fait toujours référence à votre chaîne d'origine, avec un décalage et contrainte de taille.

Donc, pour permettre à votre chaîne d'origine pour être recueillis, vous devez créer une nouvelle chaîne (à l'aide d' new String, ou ce que vous avez).

5voto

Michael Borgwardt Points 181658

Je pense que c'.smallpart gardé référencement vers les données, mais pourquoi?

Parce que les cordes de Java se composent d'un tableau de char, un décalage de début et une longueur (et le cache hashCode). Certaines opérations de Chaîne comme substring() créer un nouvel objet String qui partage l'original du tableau de char et a tout simplement décalage différent et/ou de champs de longueur. Cela fonctionne parce que le char tableau d'une Chaîne n'est jamais modifié une fois qu'il a été créé.

Cela peut économiser de la mémoire lorsque le nombre de sous-chaînes, reportez-vous à la même chaîne de base, sans les reproduire parties superposées. Comme vous l'avez remarqué, dans certaines situations, il peut conserver les données qui n'a plus besoin d'être nettoyée.

La "bonne" façon de résoudre ce problème est l' new String(String) constructeur, c'est à dire

this.smallpart = new String(data.substring(12,18));

BTW, l'ensemble de la meilleure solution serait d'éviter d'avoir de très grandes Chaînes, en premier lieu, et le traitement de toute entrée en blocs plus petits, aa quelques KO à la fois.

5voto

Kico Lobo Points 2279

En Java, les chaînes sont imutable objets et une fois qu'une chaîne est créé, celui-ci reste en mémoire jusqu'à ce qu'il est nettoyé par le garbage colector (et ce nettoyage n'est pas quelque chose que vous pouvez prendre pour acquis).

Lorsque vous appelez la méthode sous-chaîne, Java ne crée pas vraiment de nouvelles de la chaîne, mais seulement des magasins d'une plage de caractères à l'intérieur de la chaîne d'origine.

Donc, lorsque vous avez créé une nouvelle chaîne avec ce code:

this.smallpart = data.substring(12, 18) + ""; 

vous avez réellement créé une nouvelle chaîne lorsque vous concaténé le résultat avec la chaîne vide. C'est pourquoi.

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