Bagaimana cara Iterate melalui Set / HashSet tanpa Iterator?


273

Bagaimana saya bisa mengulangi Set/ HashSettanpa yang berikut ini?

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

31
Apakah Anda benar-benar mencoba menghindari penggunaan iterator, atau Anda tidak ingin melihatnya dalam kode sumber Anda ?
Jon Skeet

2
Anda dapat membuat kode lebih pendek dan lebih bersih, tetapi Anda harus menggunakan Iterator. Apakah ada alasan Anda ingin menghindarinya?
Peter Lawrey

5
Sekadar catatan dan penjelasan mengapa harus menghindari iterator: Saat ini saya sedang menghadapi masalah itu dalam game Android yang ditulis di Jawa. Saat ini saya menggunakan HashSet untuk menyimpan pendengar yang perlu diberitahu tentang acara secara teratur. Namun, berulang-ulang koleksi menyebabkan kegiatan pengumpul sampah berat yang dapat membebani loop permainan. Dan itu adalah larangan dalam permainan Java. Saya akan menulis ulang bagian-bagian ini.
tiguchi

12
@thecoshman Saya hanya berbicara dari perspektif pengembangan game Java di mana Anda ingin menghindari GC selama pembaruan status game reguler di semua biaya. Iterator hanya objek sementara berguna karena Anda tidak dapat mengatur ulang mereka ke awal, oleh karena itu mereka dapat diciptakan kembali pada setiap panggilan metode iterasi (lihat sumber ArrayList.java misalnya). Jika digunakan dalam loop game untuk mengulangi objek adegan dan mempertimbangkan setidaknya 30 pembaruan per detik Anda berakhir dengan setidaknya 60 (adegan biasanya diulang dua kali per siklus) objek iterator per detik dalam memori menunggu GC. Itu memiliki dampak besar pada Android.
tiguchi

9
Mungkin orang harus memilih struktur data yang lebih memadai dalam kasus itu? Satu set tidak dirancang untuk beralih secara efisien. Mengapa tidak menggunakan ArrayList dan beralih di atasnya dengan standar untuk loop? Tidak ada iterator tambahan yang dibuat, akses baca sangat cepat.
stef77

Jawaban:


492

Anda dapat menggunakan loop yang disempurnakan untuk :

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

//populate set

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

Atau dengan Java 8:

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

65
Saya percaya ini menggunakan iterator di belakang layar.
munyengm

22
@ munyengm Ya. Tidak ada cara untuk beralih pada set tanpa iterator, selain mengakses struktur yang mendasarinya yang menyimpan data melalui refleksi, dan mereplikasi kode yang disediakan oleh Set # iterator ...
assylias

1
Ini berfungsi, tetapi jika itu bisa memberikan masalah maka itu bukan solusi bagi saya. Saya kira saya tidak punya pilihan, saya harus menggunakan Iterator. Terima kasih untuk semuanya.
user1621988

39
@ user1621988 Masalah apa? Tidak ada masalah dengan kode yang saya berikan. Itu hanya menyediakan cara yang bagus dan bersih untuk mengulangi set tanpa harus secara eksplisit menggunakan iterator.
assylias

90

Setidaknya ada enam cara tambahan untuk beralih pada satu set. Berikut ini diketahui oleh saya:

Metode 1

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

Metode 2

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

Metode 3

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

Metode 4

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

Metode 5

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

Metode 6

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

Inilah HashSetyang saya gunakan untuk contoh saya:

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

10
Hai @ benny-neugebauer Untuk Metode 4 , Metode 5 , Metode 6 Anda dapat menghapusnya secara berlebihan stream().
Eugene T

5
Belum lagi bahwa Metode 4, Metode 5 dan Metode 6 adalah sama.
GustavoCinque

24

Mengubah set Anda menjadi array juga dapat membantu Anda untuk mengulangi elemen-elemen:

Object[] array = set.toArray();

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

45
Sekadar catatan, toArraypanggil iterator set.
assylias

13

Untuk mendemonstrasikan, pertimbangkan set berikut, yang menampung objek Person berbeda:

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

Kelas Model Orang

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. Pernyataan for memiliki formulir yang dirancang untuk iterasi melalui Koleksi dan array. Formulir ini kadang-kadang disebut sebagai pernyataan yang disempurnakan, dan dapat digunakan untuk membuat loop Anda lebih ringkas dan mudah dibaca.
for(Person p:people){
  System.out.println(p.getName());
}
  1. Java 8 - java.lang.Iterable.forEach (Konsumen)
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

Anda dapat menggunakan operasi fungsional untuk kode yang lebih rapi

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

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

Panggilan membutuhkan API 24
djdance

11

Berikut adalah beberapa tips tentang cara mengembalikan Set bersama dengan kinerja mereka:

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

Kode ini jelas.

Hasil dari durasi adalah:

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

Kita bisa melihat Lambdayang paling lama Iteratoradalah yang paling cepat.


2

Pencacahan (?):

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

Cara lain (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));

atau

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

0

Namun ada jawaban yang sangat bagus sudah tersedia untuk ini. Inilah jawaban saya:

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

Juga, jika Set ini adalah tipe kelas Kustom, misalnya: Pelanggan.

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

// Kelas pelanggan:

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.}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.