イテレータなしでSet / HashSetを反復する方法は?


273

次のようにSet/ HashSetなしでどのように反復できますか?

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

31
イテレータの使用を実際に避けようとしているのですか、それともソースコードでイテレータを見たくないだけですか?
ジョンスキート

2
コードをより短く、よりクリーンにすることができますが、イテレーターを使用する必要があります。それを避けたい理由はありますか?
Peter Lawrey 2012

5
記録のためと、イテレータを回避する理由の説明として:私は現在、Javaで記述されたAndroidゲームでその問題に直面しています。現在、私はHashSetを使用して、イベントについて定期的に通知される必要があるリスナーを格納しています。ただし、コレクションを繰り返し反復すると、ガベージコレクタのアクティビティが大量に発生し、ゲームループに負担がかかる可能性があります。そして、それはJavaゲームではノーゴーです。これらの部分を書き直します。
tiguchi

12
@thecoshman定期的にゲームの状態を更新している間は、GCを絶対に避けたいJavaゲーム開発の観点からのみ話しています。イテレータは、最初にリセットできないため、一時的に役立つオブジェクトであり、反復メソッドの呼び出しごとに再作成されます(たとえば、ArrayList.javaソースを参照)。ゲームループでシーンオブジェクトを反復し、1秒あたり少なくとも30回の更新を考慮すると、GCを待機しているメモリ内で1秒あたり60回(シーンは通常、サイクルごとに2回反復されます)の反復子オブジェクトになります。これはAndroidに大きな影響を与えます。
tiguchi 14年

9
その場合、おそらくより適切なデータ構造を選択する必要がありますか?セットは効率的に反復するように設計されていません。ArrayListを使用せずに、標準のforループで反復しませんか?追加のイテレータは作成されず、読み取りアクセスは非常に高速です。
stef77 2015

回答:


492

拡張された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 2012

22
@munyengmはい、あります。リフレクションを通じてデータを保持する基になる構造にアクセスし、Set#iteratorによって提供されるコードを複製することを除いて、イテレータなしでセットを反復処理する方法はありません...
assylias

1
これは機能しますが、問題が発生する可能性がある場合は、私にとって解決策ではありません。私は選択の余地がないと思います。イテレータを使用する必要があります。とにかくありがとう。
user1621988 2012

39
@ user1621988どのような問題ですか?私が提供したコードに問題はありません。明示的にイテレータを使用する必要なく、セットを反復するための優れたクリーンな方法を提供するだけです。
アッシリア2012

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セットのイテレータを呼び出します。
アッシリア2012

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ステートメントには、コレクションおよび配列を反復処理するために設計されたフォームがあります。このフォームは、拡張forステートメントと呼ばれることもあり、ループをよりコンパクトで読みやすくするために使用できます。
for(Person p:people){
  System.out.println(p.getName());
}
  1. Java 8-java.lang.Iterable.forEach(Consumer)
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());
    }

Java 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

また、このセットがカスタムクラスタイプの場合(例:Customer)。

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.