반복자없이 Set / HashSet을 반복하는 방법?


272

다음없이 Set/ HashSet를 반복하는 방법은 무엇입니까?

Iterator iter = set.iterator();
while (iter.hasNext()) {
    System.out.println(iter.next());
}

31
실제로 반복자를 사용하지 않으려 고합니까, 아니면 소스 코드 에서 그것을보고 싶지 않습니까?
Jon Skeet

2
코드를 더 짧고 깔끔하게 만들 수 있지만 반복자를 사용해야합니다. 피하고 싶은 이유가 있습니까?
Peter Lawrey

5
레코드와 반복자를 피하는 이유에 대한 설명으로 현재 Java로 작성된 Android 게임 에서이 문제에 직면하고 있습니다. 지금은 이벤트에 대해 정기적으로 알려야하는 리스너를 저장하기 위해 HashSet을 사용하고 있습니다. 그러나 컬렉션을 반복적으로 반복하면 가비지 수집기 활동이 많아 게임 루프에 부담을 줄 수 있습니다. 그리고 그것은 Java 게임에서 절대로 아닙니다. 이 부분들을 다시 쓰겠습니다.
tiguchi

12
@thecoshman 저는 모든 게임 비용을 정기적으로 업데이트하는 동안 GC를 피하려는 Java 게임 개발 관점에서만 이야기하고 있습니다. 반복자는 시작으로 재설정 할 수 없으므로 일시적으로 유용한 객체이므로 각 반복 메소드 호출 (예 : ArrayList.java 소스 참조)에서 다시 작성됩니다. 장면 객체를 반복하고 초당 30 개 이상의 업데이트를 고려하기 위해 게임 루프에서 사용되는 경우 GC를 기다리는 메모리에서 초당 60 개 이상의 장면 (일반적으로 사이클 당 두 번 반복됨)으로 반복됩니다. 그것은 안드로이드에 큰 영향을 미칩니다.
tiguchi

9
아마도이 경우보다 적절한 데이터 구조를 선택해야합니까? 세트는 효율적으로 반복되도록 설계되지 않았습니다. ArrayList를 사용하고 표준 for 루프로 반복하지 않는 이유는 무엇입니까? 추가 반복자가 작성되지 않으며 읽기 액세스가 매우 빠릅니다.
stef77

답변:


491

향상된 for 루프를 사용할 수 있습니다 .

Set<String> set = new HashSet<String>();

//populate set

for (String s : set) {
    System.out.println(s);
}

또는 Java 8 :

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

65
나는 이것이 배후의 반복자를 사용한다고 생각합니다.
munyengm

22
@munyengm 그렇습니다. 일련의 반복하는 방법은 ... 떨어져 반사를 통해 데이터를 보유하는 기본 구조에 액세스하고, 설정 # 반복기에 의해 제공되는 코드를 복제하는, 반복자없이 없다
assylias는

1
이것은 효과가 있지만 문제가 발생할 수 있다면 그것은 해결책이 아닙니다. 나는 선택의 여지가 없다고 생각합니다. 반복자를 사용해야합니다. 어쨌든 감사합니다.
user1621988

39
@ user1621988 어떤 문제가 있습니까? 내가 제공 한 코드에는 문제가 없습니다. 반복자를 명시 적으로 사용할 필요없이 세트를 반복하는 멋지고 깨끗한 방법을 제공합니다.
assylias

90

집합을 반복하는 추가 방법은 6 가지 이상 있습니다. 다음은 나에게 알려져 있습니다.

방법 1

// Obsolete Collection
Enumeration e = new Vector(movies).elements();
while (e.hasMoreElements()) {
  System.out.println(e.nextElement());
}

방법 2

for (String movie : movies) {
  System.out.println(movie);
}

방법 3

String[] movieArray = movies.toArray(new String[movies.size()]);
for (int i = 0; i < movieArray.length; i++) {
  System.out.println(movieArray[i]);
}

방법 4

// Supported in Java 8 and above
movies.stream().forEach((movie) -> {
  System.out.println(movie);
});

방법 5

// Supported in Java 8 and above
movies.stream().forEach(movie -> System.out.println(movie));

방법 6

// Supported in Java 8 and above
movies.stream().forEach(System.out::println);

이것은 HashSet내 예제에 사용한 것입니다.

Set<String> movies = new HashSet<>();
movies.add("Avatar");
movies.add("The Lord of the Rings");
movies.add("Titanic");

10
안녕하세요 @ benny-neugebauer 방법 4 , 방법 5 , 방법 6의 경우 중복을 간단히 제거 할 수 있습니다 stream().
유진 T

5
방법 4, 방법 5 및 방법 6은 동일하다는 것은 말할 것도 없습니다.
GustavoCinque

24

집합을 배열로 변환 하면 요소를 반복하는 데 도움이 될 수 있습니다.

Object[] array = set.toArray();

for(int i=0; i<array.length; i++)
   Object o = array[i];

45
레코드의 경우에만 toArray세트의 반복자를 호출합니다.
assylias

13

시연을 위해 다른 Person 객체를 보유하는 다음 세트를 고려하십시오.

Set<Person> people = new HashSet<Person>();
people.add(new Person("Tharindu", 10));
people.add(new Person("Martin", 20));
people.add(new Person("Fowler", 30));

개인 모델 클래스

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

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

    //TODO - getters,setters ,overridden toString & compareTo methods

}
  1. for 문은 Collections and arrays를 통한 반복을 위해 설계된 양식을 가지고 있습니다.
for(Person p:people){
  System.out.println(p.getName());
}
  1. Java 8-java.lang.Iterable.forEach (소비자)
people.forEach(p -> System.out.println(p.getName()));
default void forEach(Consumer<? super T> action)

Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception. Unless otherwise specified by the implementing class, actions are performed in the order of iteration (if an iteration order is specified). Exceptions thrown by the action are relayed to the caller. Implementation Requirements:

The default implementation behaves as if: 

for (T t : this)
     action.accept(t);

Parameters: action - The action to be performed for each element

Throws: NullPointerException - if the specified action is null

Since: 1.8

11

보다 깔끔한 코드를 위해 기능적 작업을 사용할 수 있습니다

Set<String> set = new HashSet<String>();

set.forEach((s) -> {
     System.out.println(s);
});

전화는 API 24가 필요합니다
djdance

11

다음은 퍼포먼스와 함께 세트를 반복하는 방법에 대한 팁입니다.

public class IterateSet {

    public static void main(String[] args) {

        //example Set
        Set<String> set = new HashSet<>();

        set.add("Jack");
        set.add("John");
        set.add("Joe");
        set.add("Josh");

        long startTime = System.nanoTime();
        long endTime = System.nanoTime();

        //using iterator
        System.out.println("Using Iterator");
        startTime = System.nanoTime();
        Iterator<String> setIterator = set.iterator();
        while(setIterator.hasNext()){
            System.out.println(setIterator.next());
        }
        endTime = System.nanoTime();
        long durationIterator = (endTime - startTime);


        //using lambda
        System.out.println("Using Lambda");
        startTime = System.nanoTime();
        set.forEach((s) -> System.out.println(s));
        endTime = System.nanoTime();
        long durationLambda = (endTime - startTime);


        //using Stream API
        System.out.println("Using Stream API");
        startTime = System.nanoTime();
        set.stream().forEach((s) -> System.out.println(s));
        endTime = System.nanoTime();
        long durationStreamAPI = (endTime - startTime);


        //using Split Iterator (not recommended)
        System.out.println("Using Split Iterator");
        startTime = System.nanoTime();
        Spliterator<String> splitIterator = set.spliterator();
        splitIterator.forEachRemaining((s) -> System.out.println(s));
        endTime = System.nanoTime();
        long durationSplitIterator = (endTime - startTime);


        //time calculations
        System.out.println("Iterator Duration:" + durationIterator);
        System.out.println("Lamda Duration:" + durationLambda);
        System.out.println("Stream API:" + durationStreamAPI);
        System.out.println("Split Iterator:"+ durationSplitIterator);
    }
}

코드는 자명하다.

지속 시간의 결과는 다음과 같습니다.

Iterator Duration: 495287
Lambda Duration: 50207470
Stream Api:       2427392
Split Iterator:    567294

Lambda가장 오래 걸리는 것이 가장 Iterator빠르다는 것을 알 수 있습니다 .


2

열거(?):

Enumeration e = new Vector(set).elements();
while (e.hasMoreElements())
    {
        System.out.println(e.nextElement());
    }

다른 방법 (java.util.Collections.enumeration ()) :

for (Enumeration e1 = Collections.enumeration(set); e1.hasMoreElements();)
    {
        System.out.println(e1.nextElement());
    }

자바 8 :

set.forEach(element -> System.out.println(element));

또는

set.stream().forEach((elem) -> {
    System.out.println(elem);
});

0

그러나 이에 대한 좋은 답변이 이미 있습니다. 내 대답은 다음과 같습니다.

1. set.stream().forEach(System.out::println); // It simply uses stream to display set values
2. set.forEach(System.out::println); // It uses Enhanced forEach to display set values

또한이 세트가 사용자 정의 클래스 유형 인 경우 (예 : 고객).

Set<Customer> setCust = new HashSet<>();
    Customer c1 = new Customer(1, "Hena", 20);
    Customer c2 = new Customer(2, "Meena", 24);
    Customer c3 = new Customer(3, "Rahul", 30);

setCust.add(c1);
setCust.add(c2);
setCust.add(c3);
    setCust.forEach((k) -> System.out.println(k.getId()+" "+k.getName()+" "+k.getAge()));

// 고객 클래스 :

class Customer{
private int id;
private String name;
private int age;

public Customer(int id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
} // Getter, Setter methods are present.}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.