web-dev-qa-db-fra.com

Imprimer joliment Java Collections (toString ne renvoie pas de jolis résultats)

Je souhaite imprimer un objet Stack<Integer> aussi bien que le débogueur Eclipse (c'est-à-dire [1,2,3...]), mais l'imprimer avec out = "output:" + stack ne renvoie pas ce résultat de Nice.

Juste pour clarifier, je parle de la collection intégrée de Java afin que je ne puisse pas remplacer sa toString().

Comment puis-je obtenir une version Nice imprimable de la pile?

199
Elazar Leibovich

Vous pouvez le convertir en tableau et l’imprimer ensuite avec Arrays.toString(Object[]):

System.out.println(Arrays.toString(stack.toArray()));
300
Zach Langley
String.join(",", yourIterable);

(Java 8)

47
user1016765

La classe MapUtils offerte par le projet Apache Commons offre une méthode MapUtils.debugPrint qui permet d’imprimer votre carte.

18
tlavarea

Avec Java 8 flux et collecteurs, vous pouvez le faire facilement:

String format(Collection<?> c) {
  String s = c.stream().map(Object::toString).collect(Collectors.joining(","));
  return String.format("[%s]", s);
}

tout d'abord, nous utilisons map avec Object::toString pour créer Collection<String>, puis nous utilisons un collecteur de jointure pour joindre chaque élément de la collection avec , comme délimiteur.

16
bsmk

Implémentez toString () sur la classe.

Je recommande le Apache Commons ToStringBuilder pour rendre cela plus facile. Avec cela, il vous suffit d'écrire ce type de méthode:

public String toString() {
     return new ToStringBuilder(this).
       append("name", name).
       append("age", age).
       toString(); 
}

Pour obtenir ce type de sortie:

Personne @ 7f54 [nom = Stephen, age = 29]

Il y a aussi un implémentation réflexive .

12
Chinnery

System.out.println (Collection c) imprime déjà tout type de collection dans un format lisible. Seulement si la collection contient des objets définis par l'utilisateur, vous devez implémenter toString () dans la classe définie par l'utilisateur pour afficher le contenu.

11
Shekhar

La goyave semble être une bonne option:

Iterables.toString(myIterable)

9
Ben

Je suis d'accord avec les commentaires ci-dessus sur le remplacement de toString() sur vos propres classes (et sur l'automatisation de ce processus autant que possible).

Pour les classes que vous n'avez pas définies, vous pouvez écrire une classe ToStringHelper avec une méthode surchargée pour chaque classe de bibliothèque que vous souhaitez gérer à votre guise:

public class ToStringHelper {
    //... instance configuration here (e.g. punctuation, etc.)
    public toString(List m) {
        // presentation of List content to your liking
    }
    public toString(Map m) {
        // presentation of Map content to your liking
    }
    public toString(Set m) {
        // presentation of Set content to your liking
    }
    //... etc.
}

EDIT: En réponse au commentaire de xukxpvfzflbbld, voici une implémentation possible pour les cas mentionnés précédemment.

package com.so.demos;

import Java.util.List;
import Java.util.Map;
import Java.util.Set;

public class ToStringHelper {

    private String separator;
    private String arrow;

    public ToStringHelper(String separator, String arrow) {
        this.separator = separator;
        this.arrow = arrow;
    }

   public String toString(List<?> l) {
        StringBuilder sb = new StringBuilder("(");
        String sep = "";
        for (Object object : l) {
            sb.append(sep).append(object.toString());
            sep = separator;
        }
        return sb.append(")").toString();
    }

    public String toString(Map<?,?> m) {
        StringBuilder sb = new StringBuilder("[");
        String sep = "";
        for (Object object : m.keySet()) {
            sb.append(sep)
              .append(object.toString())
              .append(arrow)
              .append(m.get(object).toString());
            sep = separator;
        }
        return sb.append("]").toString();
    }

    public String toString(Set<?> s) {
        StringBuilder sb = new StringBuilder("{");
        String sep = "";
        for (Object object : s) {
            sb.append(sep).append(object.toString());
            sep = separator;
        }
        return sb.append("}").toString();
    }

}

Ce n'est pas une implémentation complète, mais juste un démarreur.

9
joel.neely

Vous pouvez utiliser la classe "Objets" de Java (disponible depuis 1.7).

Collection<String> myCollection = Arrays.asList("1273","123","876","897");
Objects.toString(myCollection);

Sortie: 1273, 123, 876, 897

Une autre possibilité consiste à utiliser la classe "MoreObjects" de Google Guave , qui fournit de nombreuses fonctions utiles:

MoreObjects.toStringHelper(this).add("NameOfYourObject", myCollection).toString());

Sortie: NameOfYourObject = [1273, 123, 876, 897]

documents sur la goyave

5
Chisey88

Avec Apache Commons, vous souhaitez appeler

StringUtils.join(myCollection, ",")
3
JRA_TLL

En Java8

//will prints each element line by line
stack.forEach(System.out::println);

ou

//to print with commas
stack.forEach(
    (ele) -> {
        System.out.print(ele + ",");
    }
);
3
YÒGÎ

Juste modifié l'exemple précédent pour imprimer même une collection contenant des objets définis par l'utilisateur.

public class ToStringHelper {

    private  static String separator = "\n";

    public ToStringHelper(String seperator) {
        super();
        ToStringHelper.separator = seperator;

    }

    public  static String toString(List<?> l) {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        for (Object object : l) {
            String v = ToStringBuilder.reflectionToString(object);
            int start = v.indexOf("[");
            int end = v.indexOf("]");
            String st =  v.substring(start,end+1);
            sb.append(sep).append(st);
            sep = separator;
        }
        return sb.toString();
    }

    public static String toString(Map<?,?> m) {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        for (Object object : m.keySet()) {
            String v = ToStringBuilder.reflectionToString(m.get(object));
            int start = v.indexOf("[");
            int end = v.indexOf("]");
            String st =  v.substring(start,end+1);
            sb.append(sep).append(st);
            sep = separator;
        }
        return sb.toString();
    }

    public static String toString(Set<?> s) {
        StringBuilder sb = new StringBuilder();
        String sep = "";
        for (Object object : s) {
            String v = ToStringBuilder.reflectionToString(object);
            int start = v.indexOf("[");
            int end = v.indexOf("]");
            String st =  v.substring(start,end+1);
            sb.append(sep).append(st);
            sep = separator;
        }
        return sb.toString();
    }

    public static void print(List<?> l) {
        System.out.println(toString(l));    
    }
    public static void print(Map<?,?> m) {
        System.out.println(toString(m));    
    }
    public static void print(Set<?> s) {
        System.out.println(toString(s));    
    }

}
1
Shekhar

la plupart des collections ont une toString() utile dans Java de nos jours (Java7/8). Il n’est donc pas nécessaire de faire des opérations de flux pour concaténer ce dont vous avez besoin; il vous suffit de remplacer toString de votre classe de valeurs dans la collection et d’obtenir ce dont vous avez besoin.

AbstractMap et AbstractCollection implémentent toString () en appelant toString par élément.

ci-dessous est un testclass pour montrer le comportement.

import Java.util.List;
import Java.util.ArrayList;
import Java.util.Map;
import Java.util.HashMap;

public class ToString {
  static class Foo {
    int i;
    public Foo(int i) { this.i=i; }
    @Override
    public String toString() {
        return "{ i: " + i + " }";
    }
  }
  public static void main(String[] args) {
    List<Foo> foo = new ArrayList<>();
    foo.add(new Foo(10));
    foo.add(new Foo(12));
    foo.add(new Foo(13));
    foo.add(new Foo(14));
    System.out.println(foo.toString());
    // prints: [{ i: 10 }, { i: 12 }, { i: 13 }, { i: 14 }]

    Map<Integer, Foo> foo2 = new HashMap<>();
    foo2.put(10, new Foo(10));
    foo2.put(12, new Foo(12));
    foo2.put(13, new Foo(13));
    foo2.put(14, new Foo(14));
    System.out.println(foo2.toString());
    // prints: {10={ i: 10 }, 12={ i: 12 }, 13={ i: 13 }, 14={ i: 14 }}
  }
}
1
Alex

Vous pouvez essayer d'utiliser

org.Apache.commons.lang3.builder.ToStringBuilder.reflectionToString(yourCollection);
0
user1016765

Devrait fonctionner pour toute collection sauf Map, mais elle est également facile à prendre en charge. Modifiez le code pour passer ces 3 caractères comme arguments si nécessaire.

static <T> String seqToString(Iterable<T> items) {
    StringBuilder sb = new StringBuilder();
    sb.append('[');
    boolean needSeparator = false;
    for (T x : items) {
        if (needSeparator)
            sb.append(' ');
        sb.append(x.toString());
        needSeparator = true;
    }
    sb.append(']');
    return sb.toString();
}
0
Sarge Borsch

S'il s'agit de votre propre classe de collection plutôt que de celle intégrée, vous devez remplacer sa méthode toString. Eclipse appelle cette fonction pour tous les objets pour lesquels il n’a pas de formatage câblé.

0
Uri

Soyez prudent lorsque vous appelez Sop on Collection, il peut renvoyer ConcurrentModification Exception. Parce que _ en interne toString la méthode de chaque collection appelle en interne Iterator sur la collection.

0
Harneet