자바 : 컬렉션을 반복하는 가장 좋은 방법 (여기서는 ArrayList)


98

오늘 저는 이미 수백 번 사용했던 코드 조각에 도달했을 때 행복하게 코딩하고있었습니다.

컬렉션 반복 (여기서는 ArrayList)

어떤 이유에서인지 실제로 Eclipse의 자동 완성 옵션을 살펴 보았는데 궁금해했습니다.

다음 루프가 다른 루프보다 더 나은 경우는 무엇입니까?

고전적인 배열 인덱스 루프 :

for (int i = 0; i < collection.length; i++) {
  type array_element = collection.get(index);
}

반복자 hasNext () / next () :

for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
  type type = (type) iterator.next();   
}

그리고 내가 가장 좋아하는 이유는 작성하기가 너무 간단하기 때문입니다.

for (iterable_type iterable_element : collection) {

}

2
나에 관해서는 주로 3 번째 루프를 사용합니다.
Harry Joy

1
두 번째 방법으로 사용하는 것이 더 좋습니다.for (Iterator<type> iterator = collection.iterator(); iterator.hasNext();) { type type = iterator.next(); }
mike jones

4
컬렉션 인터페이스에는 "get"메서드가 포함되어 있지 않으므로 첫 번째가 항상 가능한 것은 아닙니다.
ThePerson

답변:


104

첫 번째는 요소의 색인이 필요할 때도 유용합니다. 이것은 기본적으로 ArrayLists 의 다른 두 가지 변형과 동일 하지만 LinkedList.

두 번째는 요소의 색인이 필요하지 않지만 반복 할 때 요소를 제거해야 할 때 유용합니다. 그러나 이것은 너무 장황한 IMO라는 단점이 있습니다.

세 번째 버전도 선호하는 선택입니다. 이는 짧고 인덱스 나 기본 반복자가 필요하지 않은 모든 경우에 작동합니다 (즉, 요소에 액세스 만하고 요소를 제거하거나 Collection어떤 식 으로든 수정하지 않음 -가장 일반적인 경우).


3
+1 이길. LinkedList를 언급하려고했습니다 ( 모든 의가 Collection인덱스로 검색하는 것이 저렴 하지는 않습니다 ).
The Scrum Meister 2011 년

요소를 반복하는 데 필요한 한 항상 세 번째 버전을 사용하는 것이 좋습니다. 다른 모든 컬렉션에 대한 구현이 이미 존재하고 Sun 또는 모든 JDK 구현이 모든 컬렉션이 아닌 성능을 개선하기 위해 노력하기 때문입니다.
Phani 2011 년

@Phani : 다른 두 가지 변형은 모든 JDK 구현에서도 작동합니다.
MAK 2011 년

나는 그것들이 작동하지 않을 것이라고 말하지는 않았지만, 만일 컬렉션의 구현을 위해 특정한 개선이나 성능 변경이 이루어지면 그것은 자동으로 당신의 코드에 적용될 것이고 당신은 성능을 향상시키기 위해 작성할 필요가 없습니다. 내가 의미하는 바입니다.
Phani 2011 년

1
@Phani : AFAIK 3 번째 형식은 2 번째 형식에 대한 구문 설탕 일뿐입니다 (즉, foreach 변형은 실제로 반복자를 사용합니다). 따라서 모든 성능 이점은 두 변형 모두에서 사용할 수 있습니다. 물론 첫 번째 버전은 성능상의 이점을 얻지 못할 것입니다 (예 : List트리로 구현 된 경우 실제로는 더 느립니다).
MAK 2011 년

36

그들 모두는 자신의 용도가 있습니다.

  1. 반복 가능한 항목이 있고 모든 항목을 무조건 순회해야하는 경우 :

    for (iterable_type iterable_element : 컬렉션)

  2. iterable이 있지만 조건부로 트래버스해야하는 경우 :

    for (반복기 반복기 = collection.iterator (); iterator.hasNext ();)

  3. 데이터 구조가 iterable을 구현하지 않는 경우 :

    for (int i = 0; i <collection.length; i ++)


조건부로 첫 번째 메서드를 탐색하기 위해 이렇게 할 수 있습니까? if (iterable_element.some_attribute) {// 무언가를합니다; } else {// 아무것도하지 않습니다. }. 그렇다면 구문 설탕을 제외하고는 첫 번째 방법과 두 번째 방법 사이에 본질적으로 차이가 없습니다.
토마스 응우 엔

1 단지 수와 같은 조건 트래버스 다른 사람이 사용하는 것과하는 것입니다 break및 / 또는continue
arcyqwerty

13

Java 8에는 추가로 collections의 stream () 유틸리티가 있습니다.

collection.forEach((temp) -> {
            System.out.println(temp);
});

또는

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

Wonderers 링크를 위한 Java 8 스트림 및 컬렉션에 대한 추가 정보


4

그들 중 어느 것도 다른 것보다 "더 나은"것은 없습니다. 세 번째는 나에게는 더 읽기 쉽지만 foreaches를 사용하지 않는 사람에게는 이상하게 보일 수 있습니다 (첫 번째를 선호 할 수 있음). 3 가지 모두 자바를 이해하는 사람이라면 누구나 쉽게 이해할 수 있으므로 코드에 대해 기분이 좋아지는 것을 선택하세요.

첫 번째는 가장 기본적인 패턴이므로 가장 보편적 인 패턴입니다 (배열, 제가 생각할 수있는 모든 반복 가능). 그것이 제가 생각할 수있는 유일한 차이점입니다. 더 복잡한 경우 (예 : 현재 인덱스에 대한 액세스 권한이 필요하거나 목록을 필터링해야 함)의 경우 첫 번째 및 두 번째 경우가 각각 더 의미가있을 수 있습니다. 간단한 경우 (반복 가능한 개체, 특별한 요구 사항 없음)의 경우 세 번째가 가장 깨끗해 보입니다.


2

첫 번째 옵션은 성능면에서 더 좋습니다 (ArrayList가 RandomAccess 인터페이스를 구현하므로). Java 문서에 따라 List 구현은 클래스의 일반적인 인스턴스에 대해이 루프가 다음과 같은 경우 RandomAccess 인터페이스를 구현해야합니다.

 for (int i=0, n=list.size(); i < n; i++)
     list.get(i);

이 루프보다 빠르게 실행됩니다.

 for (Iterator i=list.iterator(); i.hasNext(); )
     i.next();

도움이되기를 바랍니다. 첫 번째 옵션은 순차 액세스 목록의 경우 느립니다.


1

다음은 예입니다.

Query query = em.createQuery("from Student");
             java.util.List list = query.getResultList();
             for (int i = 0; i < list.size(); i++) 
             {

                 student = (Student) list.get(i);
                 System.out.println(student.id  + "  " + student.age + " " + student.name + " " + student.prenom);

             }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.