2017-10-04 6 views
-3

J'ai donc ce morceau de code:manipuler un StringBuilder dans un tableau de StringBuilder en java

StringBuilder[] a = new StringBuilder[5]; 
     Arrays.fill(a, new StringBuilder("asdfg")); 
     a[0].deleteCharAt(0); 
     for (StringBuilder s : a) { 
      System.out.println(s); 
     } 

et la sortie

sdfg 
sdfg 
sdfg 
sdfg 
sdfg 

Il semble que tout élément du tableau est une référence à la même objet StringBuilder, je suppose que c'est à cause de Arrays.fill(). Pourquoi cela arrive-t-il et comment puis-je résoudre ce problème? p.s: Je ne veux pas utiliser une boucle car fill() ne se comporte différemment qu'avec StringBuilder [] et je veux comprendre pourquoi.

+0

Comment voulez-vous dire "fill() se comporte différemment avec StringBuilder []"? Je suis sûr que non. – daniu

+2

Pouvez-vous indiquer ce qui est différent avec 'StringBuilder'? Pouvez-vous fournir un échantillon avec une * classe différente * qui donnera un résultat différent? –

Répondre

1

Je suis sûr que la raison de dire « fill() ne se comporte différemment avec StringBuidler[] » est parce que vous avez seulement essayé avec d'autres objets immuables et StringBuilder n'est pas. Essayez

List<String> list[] = new List[5]; 
Arrays.fill(list, new ArrayList<String>()); 
list[0].add("hello"); 
for (List l : list) { 
    System.out.println(l); 
} 

Immuable signifie que l'appel de méthodes sur une instance ne changera pas son état (comme dans StringBuilder « le cas de la String accumulée, ou dans List » s, les entrées contenues.

+0

Oh je ne savais pas que 'StringBuilder' est mutable et' String' (un de ceux que j'ai essayé) ne l'est pas. Désolée de vous avoir fait perdre votre temps. Sera plus réfléchie à partir de maintenant. –

1

De l'API, Arrays.fill ...

Affecte la référence d'objet spécifié à chaque élément du tableau spécifié d'objets.

Alors oui, il est la même référence, et malheureusement, vous aura besoin d'une certaine forme d'itération pour attribuer un StringBuilder différent à tous les éléments.

5

Le comportement que vous voyez est attendu.

mentionnant the javadoc of Arrays.fill():

Affecte la référence de l'objet spécifié à chaque élément de l'ensemble spécifié d'objets.

Emphasis mine.

La référence est ici val dans le prototype (rappel: public static void fill(Object[] a, Object val), qui est votre new StringBuilder("asdfg")

Si vous voulez remplir chaque élément du tableau avec différents éléments, vous avez besoin pour faire défiler les indices de tableau. et remplir avec un nouvel objet à chaque fois par exemple (en utilisant Java 8):.

IntStream.range(O, a.length).foreach(index -> a[index] = new StringBuilder("asdfg")); 

Comme une note de côté, vous auriez pu utiliser un IntStream directement pour construire votre tableau, même si je ne suis pas sûr que le code est vraiment lisible. Avertissement d'abus d'API Stream!

final StringBuilder[] a = IntStream.range(0, 5) 
    .mapToObj(ignored -> new StringBuilder("asdfg")) 
    .toArray(StringBuilder[]::new);