293

How can I iterate over a Set/HashSet without the following?

Iterator iter = set.iterator();
while (iter.hasNext()) {
    System.out.println(iter.next());
}
UrsinusTheStrong
  • 1,157
  • 1
  • 15
  • 29
user1621988
  • 3,825
  • 8
  • 24
  • 31
  • 31
    Are you actually trying to avoid the use of an iterator, or do you just not want to see it in your *source* code? – Jon Skeet Sep 17 '12 at 08:46
  • 2
    You can make the code shorter and cleaner, but you have to use an Iterator. Is there a reason you want to avoid it? – Peter Lawrey Sep 17 '12 at 08:46
  • 2
    What is your reason for wanting to avoid the structures provided in the language for the purpose you want to accomplish? – user207421 Sep 17 '12 at 10:13
  • 5
    Just for the record and as explanation of why to avoid the iterator: I'm currently facing that issue in an Android game written in Java. Right now I'm using a HashSet for storing listeners that need to be regularly notified about events. However, repeatedly iterating collections causes heavy garbage collector activity that can burden the game loop. And that's a no-go in a Java game. I'm going to rewrite these parts. – tiguchi Jan 28 '13 at 19:36
  • @NobuGames do you have something further to read regarding your claim that iterators cases heavy garbage collector activity? – thecoshman Jan 27 '14 at 11:24
  • 12
    @thecoshman I'm talking only from a Java game development perspective where you want to avoid GC during regular game state updates at all costs. Iterators are only temporarily useful objects since you cannot reset them to the start, therefore they get recreated on each iteration method call (see ArrayList.java source for example). If used in a game loop for iterating scene objects and considering at least 30 updates per second you end up with at least 60 (scene is usually iterated twice per cycle) iterator objects per second in memory waiting for GC. That has a big impact on Android. – tiguchi Jan 27 '14 at 17:40
  • 9
    Perhaps one should pick a more adequate data structure in that case? A set's not designed to iterate over efficiently. Why not use an ArrayList and iterate over it with a standard for loop? No additional iterators are created, read access is very fast. – stef77 Jul 23 '15 at 07:45
  • set.forEach(System.out::println); – Emad Aghayi Nov 05 '18 at 22:26
  • @stef77 What if you want a collection without duplicates that can add in O(1) and yet you need to iterate on it often? – Joffrey Dec 04 '18 at 14:46

8 Answers8

510

You can use an enhanced for loop:

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

//populate set

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

Or with Java 8:

set.forEach(System.out::println);
Jared Burrows
  • 50,718
  • 22
  • 143
  • 180
assylias
  • 297,541
  • 71
  • 621
  • 741
  • 66
    I believe this uses an iterator behind the scenes. – munyengm Sep 17 '12 at 08:45
  • 22
    @munyengm Yes it does. There is no way to iterate over a set without an iterator, apart from accessing the underlying structure that holds the data through reflection, and replicating the code provided by Set#iterator... – assylias Sep 17 '12 at 08:46
  • 1
    This works, but if it could gives issues then it's not the solution for me. I guess i have no choose, i must use Iterator. Thanks for all anyway. – user1621988 Sep 17 '12 at 08:55
  • 43
    @user1621988 What issues? There are no issues with the code I provided. It just provides a nice and clean way to iterate over a set without having to explicitly use an iterator. – assylias Sep 17 '12 at 08:56
105

There are at least six additional ways to iterate over a set. The following are known to me:

Method 1

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

Method 2

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

Method 3

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

Method 4

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

Method 5

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

Method 6

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

This is the HashSet which I used for my examples:

Set<String> movies = new HashSet<>();
movies.add("Avatar");
movies.add("The Lord of the Rings");
movies.add("Titanic");
Benny Neugebauer
  • 40,817
  • 21
  • 196
  • 177
25

Converting your set into an array may also help you for iterating over the elements:

Object[] array = set.toArray();

for(int i=0; i<array.length; i++)
   Object o = array[i];
Juvanis
  • 25,000
  • 3
  • 61
  • 84
13

To demonstrate, consider the following set, which holds different Person objects:

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

Person Model Class

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. The for statement has a form designed for iteration through Collections and arrays .This form is sometimes referred to as the enhanced for statement, and can be used to make your loops more compact and easy to read.
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
Tharindu Rajarathna
  • 760
  • 1
  • 8
  • 20
12

You can use functional operation for a more neat code

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

set.forEach((s) -> {
     System.out.println(s);
});
Samuel Moshie
  • 500
  • 5
  • 18
11

Here are few tips on how to iterate a Set along with their performances:

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

The code is self explanatory.

The result of the durations are:

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

We can see the Lambda takes the longest while Iterator is the fastest.

Pritam Banerjee
  • 15,297
  • 10
  • 71
  • 92
2

Enumeration(?):

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

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

or

set.stream().forEach((elem) -> {
    System.out.println(elem);
});
CamelTM
  • 1,167
  • 10
  • 13
0

However there are very good answers already available for this. Here is my answer:

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

Also, if this Set is of Custom class type, for eg: 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()));

// Customer class:

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.}
garima garg
  • 137
  • 8