[java] Java에서 List의 모든 요소를 ​​인쇄하는 방법은 무엇입니까?

의 모든 요소를 ​​인쇄하려고 List하지만 Object값 이 아닌 포인터를 인쇄하고 있습니다.

이것은 내 인쇄 코드입니다 …

for(int i=0;i<list.size();i++){
    System.out.println(list.get(i));
} 

아무도 요소의 가치를 인쇄하지 않는 이유를 알려주세요.



답변

다음은 목록 구성 요소를 인쇄하는 방법에 대한 예입니다.

public class ListExample {

    public static void main(String[] args) {
        List<Model> models = new ArrayList<>();

        // TODO: First create your model and add to models ArrayList, to prevent NullPointerException for trying this example

        // Print the name from the list....
        for(Model model : models) {
            System.out.println(model.getName());
        }

        // Or like this...
        for(int i = 0; i < models.size(); i++) {
            System.out.println(models.get(i).getName());
        }
    }
}

class Model {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


답변

다음은 컴팩트하고 예제 코드에서 루프를 피하고 멋진 쉼표를 제공합니다.

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

그러나 다른 사람들이 지적했듯이 목록 내부의 객체에 대해 현명한 toString () 메소드가 구현되어 있지 않으면 관찰중인 객체 포인터 (사실 해시 코드)를 얻게됩니다. 목록에 있든 없든 상관 없습니다.


답변

Java 8부터 List는 다음과 같이 메소드 참조 “System.out :: println”과 결합 할 수있는 기본 “forEach”메소드를 상속합니다.

list.forEach(System.out::println);


답변

System.out.println(list);//toString() is easy and good enough for debugging.

toString()AbstractCollection 깨끗하고 쉬운 것입니다 . AbstractList의 하위 클래스 AbstractCollection, 그래서 루프 필요 없음 toArray ()에 대한 필요.

이 컬렉션의 캐릭터 라인 표현을 돌려줍니다. 문자열 표현은 반복자에 의해 반환되는 순서대로 컬렉션의 요소 목록으로 구성되며, 대괄호 ( “[]”)로 묶습니다. 인접한 요소는 “,”(쉼표 및 공백) 문자로 구분됩니다. 요소는 String.valueOf (Object)에 의해 문자열로 변환됩니다.

목록에서 사용자 정의 객체를 사용하는 경우 Student와 toString()같이 의미있는 출력을 얻으려면 메소드 를 재정의해야합니다 (항상이 메소드를 재정의하는 것이 좋습니다)

아래 예를 참조하십시오.

public class TestPrintElements {

    public static void main(String[] args) {

        //Element is String, Integer,or other primitive type
        List<String> sList = new ArrayList<String>();
        sList.add("string1");
        sList.add("string2");
        System.out.println(sList);

        //Element is custom type
        Student st1=new Student(15,"Tom");
        Student st2=new Student(16,"Kate");
        List<Student> stList=new ArrayList<Student>();
        stList.add(st1);
        stList.add(st2);
        System.out.println(stList);
   }
}


public  class Student{
    private int age;
    private String name;

    public Student(int age, String name){
        this.age=age;
        this.name=name;
    }

    @Override
    public String toString(){
        return "student "+name+", age:" +age;
    }
}

산출:

[string1, string2]
[student Tom age:15, student Kate age:16]


답변

자바 8 스트림 접근

list.stream().forEach(System.out::println);


답변

목록에있는 개체는 toString화면에 의미있는 것을 인쇄하기 위해 구현 되어야합니다 .

차이점을 확인하기위한 빠른 테스트가 있습니다.

public class Test {

    public class T1 {
        public Integer x;
    }

    public class T2 {
        public Integer x;

        @Override
        public String toString() {
            return x.toString();
        }
    }

    public void run() {
        T1 t1 = new T1();
        t1.x = 5;
        System.out.println(t1);

        T2 t2 = new T2();
        t2.x = 5;
        System.out.println(t2);

    }

    public static void main(String[] args) {
        new Test().run();
    }
}

그리고 이것이 실행될 때 화면에 출력되는 결과는 다음과 같습니다.

t1 = Test$T1@19821f
t2 = 5

T1은 toString 메소드를 대체하지 않으므로 인스턴스 t1은 그다지 유용하지 않은 것으로 인쇄됩니다. 반면에 T2는 toString을 재정의하므로 I / O에서 사용될 때 인쇄되는 내용을 제어하고 화면에서 조금 더 나은 것을 볼 수 있습니다.


답변

Java 8 구문을 List<String> stringList사용하여 여러 가지 방법으로 인쇄 할 수있는 것을 고려하십시오 .

stringList.forEach(System.out::println);                            // 1) Iterable.forEach
stringList.stream().forEach(System.out::println);                   // 2) Stream.forEach (order maintained generally but doc does not guarantee)
stringList.stream().forEachOrdered(System.out::println);            // 3) Stream.forEachOrdered (order maintained always)
stringList.parallelStream().forEach(System.out::println);           // 4) Parallel version of Stream.forEach (order not maintained)
stringList.parallelStream().forEachOrdered(System.out::println);    // 5) Parallel version ofStream.forEachOrdered (order maintained always)

이러한 접근 방식은 어떻게 다릅니 까?

첫 번째 방법 ( Iterable.forEach) –
컬렉션의 반복자는 일반적으로 사용되며, 즉하도록 설계 르파 가 던지는 것이다 수단 ConcurrentModificationException기본 모음 인 경우 구조적으로 개질 된 반복 동안. 에서 언급 한 바와 같이 문서 에 대한 ArrayList:

구조적 수정은 하나 이상의 요소를 추가 또는 삭제하거나 배킹 배열의 크기를 명시 적으로 조정하는 작업입니다. 단지 요소의 값을 설정하는 것은 구조적인 수정이 아닙니다.

따라서 ArrayList.forEach값 을 설정하는 것은 아무런 문제없이 허용됩니다. 그리고 동시 수집의 경우, 예를 들어 ConcurrentLinkedQueue반복자가 약하게 일관성 이 있을 것 입니다. 즉, 전달 된 조치가 예외가 발생 forEach하지 않고 구조적으로 변경 될 수 있음을 의미합니다 ConcurrentModificationException. 그러나 여기서 수정 사항은 해당 반복에서 표시되거나 표시되지 않을 수 있습니다.

두 번째 접근법 ( Stream.forEach)-
순서가 정의되지 않았습니다. 순차적 인 스트림에서는 발생하지 않을 수 있지만 사양에서는이를 보증하지 않습니다. 또한 그 행동은 본질적으로 방해가되지 않아야한다. doc 에서 언급했듯이 :

이 작업의 동작은 명시 적으로 비 결정적입니다. 병렬 스트림 파이프 라인의 경우이 작업은 스트림의 발생 순서를 존중한다고 보장하지는 않습니다. 병렬 처리의 이점을 희생 할 수 있습니다.

세 번째 접근 ( Stream.forEachOrdered)-
스트림의 발생 순서에 따라 작업이 수행됩니다. 따라서 주문이 중요 할 때마다 다시 forEachOrdered생각하지 않아도됩니다. 문서 에서 언급했듯이 :

스트림에 정의 된 발생 순서가있는 경우 스트림발생 순서 로이 스트림의 각 요소에 대해 작업을 수행합니다 .

이상 반복하는 동안 동기화 수집 첫 번째 방법은 모든 걸쳐 그들이 잠금 및 비의 이미 확립 된 규칙에 의존하지 않는 콜렉션의 spliterator를 사용하는 액션 메소드에 있지만, 스트림의 경우에는 통화를 개최 할하면 컬렉션의 잠금을 취할 것 -간섭. 반복하는 동안 스트림을 수집하는 콜렉션이 수정되는 경우 a ConcurrentModificationException가 발생하거나 일관되지 않은 결과가 발생할 수 있습니다.

네 번째 접근법 (병렬 Stream.forEach)-
이미 언급했듯이 병렬 스트림의 경우 예상되는 만남 순서를 존중한다고 보장하지 않습니다. 절대로 다른 요소에 대해 다른 스레드에서 작업이 수행 될 수 있습니다 forEachOrdered.

다섯째 접근법 (병렬 Stream.forEachOrdered) –
forEachOrdered스트림이 순차적 또는 병렬인지 여부에 관계없이 사실 소스에 의해 지정된 순서로 요소를 처리한다. 따라서 이것을 병렬 스트림과 함께 사용하는 것은 의미가 없습니다.