การพิมพ์คอลเล็กชัน Java อย่างดี (toString ไม่ส่งคืนเอาต์พุตสวย)


211

ฉันต้องการพิมพ์Stack<Integer>วัตถุเช่นเดียวกับที่ Eclipse debugger ทำ (เช่น[1,2,3...]) แต่การพิมพ์ด้วยout = "output:" + stackไม่ได้ผลลัพธ์ที่ดีเท่านี้

เพื่อชี้แจงฉันกำลังพูดถึงคอลเลกชันในตัวของ Java ดังนั้นฉันจึงไม่สามารถแทนที่toString()ได้

ฉันจะรับสแต็กรุ่นที่พิมพ์ได้ดีได้อย่างไร


7
อย่างน้อยที่สุดของ Java 7 AbstractCollection@toString(และเช่นนั้นString + Stack) จะพิมพ์ตามที่คุณต้องการ
Ciro Santilli 法轮功冠状病六四事件法轮功

คำตอบ:


317

คุณสามารถแปลงเป็นอาเรย์แล้วพิมพ์ด้วยArrays.toString(Object[]):

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

11
ฉันชอบมัน. ง่ายสะอาด ในการเป็นคอลเล็คชั่นที่ซื่อสัตย์ก็จำเป็นต้องมีวิธี toString ด้วยเช่นกัน แต่ก็สามารถใช้ได้เช่นกัน
Tovi7

1
@ Tovi7 อาจจะไม่ใช่เพราะ OOTB Collections ส่วนใหญ่มีให้อ่าน toString () s อยู่แล้วในขณะที่ Array นั้นไม่สามารถทำได้
Max Nanasy

@Boosha ยังต้องใช้เวลา O (n) ในการแปลงสแต็คเป็นสตริงและเวลา O (n) ในการพิมพ์สตริงไปยังคอนโซล
Zach Langley

stack.toArray()อาจมีราคาแพงมากซีพียูเวลาและหน่วยความจำที่ชาญฉลาด โซลูชันที่วนซ้ำในคอลเลกชันดั้งเดิม / ซ้ำได้อาจจะเป็นการสิ้นเปลืองทรัพยากรน้อยลง
AlikElzin-kilaka

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

(Java 8)


12
yourIterable ต้องเป็น Iterable <? ขยาย CharSequence>
นาธาน

3
String.join (",", yourCollection.stream (). map (o -> o.toString ()). collect (Collector.toList ()))
user1016765

@ user1016765 yourCollection.stream().map( o -> o.toString() ).collect( joining(",") ))ดีกว่าเพราะคุณอ่านจากซ้ายไปขวาคุณไม่จำเป็นต้องมองย้อนกลับไปที่ด้านหน้าเพื่อคำนวณในสมองของคุณว่าทำอะไรกับรายการระดับกลาง
cdalxndr

18

ด้วย java 8 สตรีมและนักสะสมมันสามารถทำได้อย่างง่ายดาย:

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

ก่อนอื่นเราใช้mapกับObject::toStringเพื่อสร้างCollection<String>และจากนั้นใช้การเข้าร่วมสะสมเพื่อเข้าร่วมทุกรายการในคอลเลกชันด้วย,เป็นตัวคั่น


22
ฉันต้องรอไม่ให้ลบคำว่า 'ง่าย' ออกจากคำตอบ ;-) Collections.toString(stack)จะง่าย
FrVaBe

ทำไมการโทรถึง String.format () เป็นเพียงการได้รับวงเล็บเหลี่ยมหรือไม่
Jolta

18

คลาส MapUtils ที่นำเสนอโดยโครงการ Apache Commons เสนอMapUtils.debugPrintวิธีการที่จะพิมพ์แผนที่ของคุณ


ไม่ใช่ที่ฉันรู้ ฉันไม่คุ้นเคยกับห้องสมุด Guava มากนัก แต่ฉันจะไม่แปลกใจถ้ามี
tlavarea

ไม่จำเป็นสำหรับสิ่งนี้อย่างน้อยใน Java 6 เพราะAbstractMap # toStringทำไปแล้ว คำถามเฉพาะแผนที่: stackoverflow.com/questions/2828252/map-to-string-in-java
Ciro Santilli 郝海东冠状病病六四事件法轮功

12

System.out.println (Collection c) พิมพ์คอลเลกชันประเภทใด ๆ ในรูปแบบที่อ่านได้แล้ว เฉพาะเมื่อคอลเลกชันมีวัตถุที่ผู้ใช้กำหนดคุณจะต้องใช้ toString () ในคลาสที่ผู้ใช้กำหนดเพื่อแสดงเนื้อหา


12

ใช้ toString () บนคลาส

ฉันแนะนำApache Commons ToStringBuilderเพื่อให้ง่ายขึ้น ด้วยคุณเพียงแค่ต้องเขียนวิธีการนี้:

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

เพื่อรับเอาต์พุตประเภทนี้:

คน @ 7f54 [ชื่อ = สตีเฟ่นอายุ = 29]

นอกจากนี้ยังมีการดำเนินการสะท้อนแสง


ToStringBuilder มักใช้กับถั่วและวัตถุที่มีข้อมูลน้อยกว่าสำหรับโครงสร้างข้อมูลที่ซับซ้อน หากวัตถุสแต็คไม่ได้พิมพ์รายการที่เก็บไว้ทั้งหมดนี้จะไม่ช่วย
Uri

2
การใช้การสะท้อน ToStringBuilder, HashCodeBuilder และ EqualsBuilder นั้นไร้ประโยชน์อย่างมาก แม้ว่าผลลัพธ์จะโอเค แต่คลาสเหล่านี้แทบจะไม่เป็นจุดสูงสุดของสัปดาห์ ...
Jan Hruby

2
คำถามชัดเจนว่าชั้นเรียนเป็นคอลเลกชันในตัวดังนั้น toString () ไม่สามารถแก้ไขได้
Rasmus Kaj


9

ฉันเห็นด้วยกับความคิดเห็นข้างต้นเกี่ยวกับการเอาชนะtoString()ในชั้นเรียนของคุณเอง (และเกี่ยวกับกระบวนการอัตโนมัติให้มากที่สุด)

สำหรับคลาสที่คุณไม่ได้กำหนดคุณสามารถเขียนToStringHelperคลาสด้วยวิธีโอเวอร์โหลดสำหรับแต่ละคลาสไลบรารีที่คุณต้องการจัดการกับรสนิยมของคุณเอง:

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

แก้ไข: ตอบสนองต่อความคิดเห็นโดย xukxpvfzflbbld นี่คือการดำเนินการที่เป็นไปได้สำหรับกรณีที่กล่าวถึงก่อนหน้านี้

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

}

นี่ไม่ใช่การใช้งานเต็มรูปแบบ แต่เป็นเพียงการเริ่มต้น


7

คุณสามารถใช้คลาส "วัตถุ" จาก JAVA (ซึ่งมีให้ตั้งแต่ 1.7)

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

เอาท์พุต: 1273, 123, 876, 897

อีกความเป็นไปได้คือการใช้คลาส "MoreObjects" จาก Google Guaveซึ่งมีฟังก์ชั่นตัวช่วยที่มีประโยชน์มากมาย:

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

เอาต์พุต: NameOfYourObject = [1273, 123, 876, 897]

เอกสารฝรั่ง


1
Objects.toString()เพียงแค่โทรtoString()หาคอลเลกชัน ในตัวอย่างของคุณใช้งานได้เนื่องจากสันนิษฐานว่าtoString()ในคอลเลกชันที่ได้รับการสนับสนุนมากมายเกิดขึ้นกับงานพิมพ์ที่สวยงาม
GuyPaddock


3

ใน Java8

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

หรือ

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

1

เพิ่งแก้ไขตัวอย่างก่อนหน้านี้เพื่อพิมพ์ชุดรวมที่มีวัตถุที่ผู้ใช้กำหนด

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

คอลเล็กชันส่วนใหญ่มีประโยชน์toString()ใน java วันนี้ (Java7 / 8) ดังนั้นจึงไม่จำเป็นต้องทำการสตรีมเพื่อเชื่อมต่อสิ่งที่คุณต้องการเพียงแค่แทนที่toStringค่าระดับของคุณในคอลเลกชันและคุณได้รับสิ่งที่คุณต้องการ

ทั้งAbstractMapและAbstractCollectionใช้ toString () โดยการเรียก toString ต่อองค์ประกอบ

ด้านล่างเป็นคลาสทดสอบเพื่อแสดงพฤติกรรม

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

โซลูชันทางเลือกอาจแปลงคอลเลกชันของคุณในรูปแบบJSONและพิมพ์ Json-String ข้อดีคือ Object-String ที่จัดรูปแบบและอ่านได้ดีโดยไม่จำเป็นต้องใช้toString()โดยไม่จำเป็นต้องของการดำเนินการที่

ตัวอย่างการใช้Gsonของ Google :

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

หากนี่เป็นคลาสคอลเล็กชันของคุณเองแทนที่จะเป็นบิวด์อินคุณต้องแทนที่เมธอด toString Eclipse เรียกฟังก์ชันนั้นสำหรับวัตถุใด ๆ ที่ไม่มีการฟอร์แมตแบบมีสายฮาร์ด


และ eclipse จัดรูปแบบคลาสเหล่านั้นด้วยการจัดรูปแบบแบบมีสายฮาร์ดได้อย่างไร นั่นคือสิ่งที่ฉันกำลังมองหา
Elazar Leibovich

0

ระวังเมื่อเรียก Sop on Collection มันสามารถโยนConcurrentModificationข้อยกเว้น เพราะtoStringวิธีการภายในของแต่ละคอลเลกชันเรียกภายในIteratorคอลเลกชัน


0

ควรทำงานกับคอลเลกชันใด ๆยกเว้นMapแต่มันก็ง่ายที่จะสนับสนุนเช่นกัน แก้ไขรหัสเพื่อส่งต่อ 3 ตัวอักษรเหล่านี้เป็นอาร์กิวเมนต์หากจำเป็น

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

มีสองวิธีที่คุณสามารถทำให้งานของคุณง่ายขึ้น 1. นำเข้าห้องสมุด Gson 2. ใช้ลอมบอก

ทั้งคู่ช่วยคุณสร้าง String จากวัตถุตัวอย่าง Gson จะแยกวัตถุของคุณ lombok จะแทนที่วัตถุชั้นเรียนของคุณไปยังวิธีการสตริง

ฉันยกตัวอย่างเกี่ยวกับ Gson prettyPrint ฉันสร้างคลาสตัวช่วยเพื่อพิมพ์วัตถุและชุดของวัตถุ หากคุณใช้ลอมบอกคุณสามารถทำเครื่องหมายคลาสของคุณเป็น @ToString และพิมพ์วัตถุของคุณโดยตรง

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

}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.