Java Koleksiyonlarını Güzel Şekilde Yazdırma (toString Oldukça Çıktı Vermiyor)


211

Bir Stack<Integer>nesneyi Eclipse hata ayıklayıcısının yaptığı kadar güzel yazdırmak istiyorum (yani [1,2,3...]) ancak yazdırmak out = "output:" + stackbu güzel sonucu döndürmez.

Sadece açıklığa kavuşturmak için, Java'nın yerleşik koleksiyonundan bahsediyorum, bu yüzden onu geçersiz kılamam toString().

Yığının güzel yazdırılabilir bir sürümünü nasıl edinebilirim?


7
En azından Java 7'den itibaren, AbstractCollection@toString(ve böylece String + Stack) zaten istediğiniz gibi yazdırıyor.
Ciro Santilli 法轮功 冠状 :0 六四 事件 法轮功

Yanıtlar:


317

Bir diziye dönüştürebilir ve daha sonra şu şekilde yazdırabilirsiniz Arrays.toString(Object[]):

System.out.println(Arrays.toString(stack.toArray()));

11
Bunu sevdim. Basit, temiz. Dürüst olmak gerekirse Koleksiyonlar'ın da toString yöntemine ihtiyacı vardır, ancak bu da işe yarar.
Tovi7

1
@ Tovi7 OOTB Koleksiyonlarının çoğu zaten Diziler () için okunabilir olduğundan, diziler sunmadığından büyük olasılıkla böyle değildir.
Max Nanasy

@Boosha ayrıca yığını bir dizeye dönüştürmek için O (n) ve dizeyi konsola yazdırmak için O (n) zaman alır
Zach Langley

stack.toArray()çok pahalı, işlemci, zaman ve bellek akıllıca olabilir. orijinal koleksiyon / yinelenebilir üzerinden yinelenen bir çözüm muhtemelen daha az kaynak tüketir.
AlikElzin-kilaka

52
String.join(",", yourIterable);

(Java 8)


12
Yinelenebilir Yinelenebilir olmalıdır <? CharSequence'ı genişletir
Nathan

3
String.join (",", yourCollection.stream (). Map (o -> o.toString ()). Toplamak (Collectors.toList ()))
user1016765 9:16

@ user1016765 yourCollection.stream().map( o -> o.toString() ).collect( joining(",") ))daha iyi çünkü soldan sağa okuduğunuzda, ara listeyle ne yapıldığını beyninizde hesaplamak için ön tarafa bakmanıza gerek yok
cdalxndr

18

Java 8 akışları ve toplayıcıları ile kolayca yapılabilir:

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

İlk kullandığımız mapile Object::toStringoluşturmak Collection<String>ve daha sonra birlikte koleksiyonunda her öğeyi katılmak katılmadan kollektörü kullanın ,sınırlayıcı olarak.


22
Cevabı 'kolayca' kaldırmak için geri tutmak zorunda kaldı ;-) Collections.toString(stack)kolay olurdu.
FrVaBe

Neden String.format () çağrısı? Sadece köşeli parantez almak mı?
Jolta

18

Apache Commons projesi tarafından sunulan MapUtils sınıfı MapUtils.debugPrint, haritanızı güzel bir şekilde yazdıracak bir yöntem sunar .


Bildiğim kadarıyla hayır. Guava kütüphanesine çok aşina değilim ama olsaydı şaşırmazdım.
tlavarea

Buna gerek yok, en azından Java 6'da, çünkü AbstractMap # toString zaten yapıyor. Sadece harita sorusu: stackoverflow.com/questions/2828252/map-to-string-in-java
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

12

System.out.println (Koleksiyon c) zaten her türlü koleksiyonu okunabilir biçimde yazdırır. Yalnızca koleksiyon kullanıcı tanımlı nesneler içeriyorsa, içeriği görüntülemek için kullanıcı tanımlı sınıfta toString () yöntemini uygulamanız gerekir.


12

Sınıfa toString () uygulayın.

Bunu kolaylaştırmak için Apache Commons ToStringBuilder'ı tavsiye ederim . Bununla birlikte, sadece bu tür bir yöntem yazmanız gerekir:

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

Bu tür çıktıları elde etmek için:

Kişi @ 7f54 [name = Stephen, yaş = 29]

Bir de bulunmaktadır yansıtıcı uygulama .


ToStringBuilder genellikle bilgi taşıyan fasulye ve nesneler için daha uygulanabilir, karmaşık veri yapıları için daha az geçerlidir. Yığın nesnesi depolanan tüm öğeleri yazdırmazsa, bu yardımcı olmaz.
Uri

2
yansıma kullanımı ToStringBuilder, HashCodeBuilder ve EqualsBuilder oldukça etkisizdir. Çıktı tamam olmasına rağmen, bu sınıflar neredeyse haftanın performans zirvesi değil ...
Jan Hruby

2
Soru açıkça sınıfın yerleşik bir koleksiyon olduğunu söylüyor, bu nedenle toString () değiştirilemez.
Rasmus Kaj


9

toString()Kendi sınıflarınızda geçersiz kılma (ve bu süreci olabildiğince otomatik hale getirme) hakkındaki yukarıdaki yorumlara katılıyorum .

Eğer sınıflar için vermedi tanımlamak, bir yazabilirsiniz ToStringHelperkendi damak zevkine ele sahip istediğiniz her kütüphane sınıf için bir aşırı yüklenme yöntemi ile sınıf:

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.
}

DÜZENLEME: xukxpvfzflbbld tarafından yapılan yoruma yanıt olarak, burada daha önce belirtilen durumlar için olası bir uygulama.

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();
    }

}

Bu tam bir uygulama değil, sadece bir başlangıç.


7

JAVA'dan ( Nesneler 1.7 sınıfını kullanabilirsiniz) (1.7'den beri kullanılabilir)

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

Çıktı: 1273, 123, 876, 897

Başka bir olasılık, birçok yararlı yardımcı işlev sağlayan Google Guave'den "MoreObjects" sınıfını kullanmaktır :

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

Çıktı: NameOfYourObject = [1273, 123, 876, 897]

Guava belgeleri


1
Objects.toString()sadece toString()koleksiyon çağırır . Örneğinizde bu, muhtemelen toString()dizi destekli koleksiyonda güzel bir şekilde yazdırıldığı için çalışır.
GuyPaddock

3

İle Apache Commons 3 , aramak istediğiniz

StringUtils.join(myCollection, ",")

3

Java8'de

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

veya

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

1

Sadece kullanıcı tanımlı nesneler içeren koleksiyonu bile yazdırmak için önceki örnek değiştirildi.

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

Çoğu koleksiyon toString()bu günlerde java'da yararlıdır (Java7 / 8). Bu nedenle, ihtiyacınız olanı birleştirmek için akış işlemleri yapmaya gerek yoktur, sadece geçersiz kılıntoString , koleksiyondaki değer sınıfınızı ve ihtiyacınız olanı elde edin.

hem AbstractMap ve AbstractCollection öğe başına toString çağırarak toString () uygulanması.

Aşağıda davranışı göstermek için bir test sınıfı bulunmaktadır.

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

JSON

Alternatif bir çözüm, koleksiyonunuzu JSON biçiminde dönüştürmek ve Json-String'i yazdırmak olabilir. Avantajı iyi biçimlendirilmiş ve okunabilir bir Object-String toString().

Google'ın Gson'unu kullanan örnek :

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

...

    printJsonString(stack);

...
public static void printJsonString(Object o) {
    GsonBuilder gsonBuilder = new GsonBuilder();
    /*
     * Some options for GsonBuilder like setting dateformat or pretty printing
     */
    Gson gson = gsonBuilder.create();
    String json= gson.toJson(o);
    System.out.println(json);
}

0

Bu, yerleşik olandan ziyade kendi toplama sınıfınızsa, toString yöntemini geçersiz kılmanız gerekir. Eclipse, bu işlevi sabit kablolu biçimlendirmesi olmayan nesneler için çağırır.


Tutulma, bu sınıfları sabit kablolu biçimlendirmeyle nasıl biçimlendirir? Aradığım şey bu.
Elazar Leibovich

0

Koleksiyona Sop çağırırken dikkatli olun, ConcurrentModificationİstisna atabilir . Çünkü toStringher Koleksiyonun dahili yöntemi Koleksiyon'u dahili olarak çağırır Iterator.


0

Bunun dışında herhangi bir koleksiyon için çalışmalı Map, ancak desteklemesi de kolaydır. Gerekirse bu 3 karakteri bağımsız değişken olarak geçirmek için kodu değiştirin.

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

Kullanmayı deneyebilirsiniz

org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(yourCollection);

0

Çalışmanızı basitleştirmenin iki yolu vardır. 1. Gson kütüphanesini içe aktarın. 2. Lombok kullanın.

Her ikisi de nesne örneğinden String oluşturmanıza yardımcı olur. Gson nesnenizi ayrıştırır, lombok sınıf nesnenizi geçersiz kılar.

Gson prettyPrint hakkında bir örnek verdim, nesneyi ve nesne koleksiyonunu yazdırmak için yardımcı sınıf oluşturuyorum. Lombok kullanıyorsanız, sınıfınızı @ToString olarak işaretleyebilir ve nesnenizi doğrudan yazdırabilirsiniz.

@Scope(value = "prototype")
@Component
public class DebugPrint<T> {
   public String PrettyPrint(T obj){
      Gson gson = new GsonBuilder().setPrettyPrinting().create();
      return gson.toJson(obj);
   }
   public String PrettyPrint(Collection<T> list){
      Gson gson = new GsonBuilder().setPrettyPrinting().create();
      return list.stream().map(gson::toJson).collect(Collectors.joining(","));
   }

}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.