¿Cómo iterar sobre un Set/HashSet sin un iterador?

7 minutos de lectura

avatar de usuario
usuario1621988

¿Cómo puedo iterar sobre un Set/HashSet sin lo siguiente?

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

  • ¿Está realmente tratando de evitar el uso de un iterador, o simplemente no quiere verlo en su fuente ¿código?

    – Jon Skeet

    17 de septiembre de 2012 a las 8:46

  • Puede hacer que el código sea más corto y limpio, pero debe usar un iterador. ¿Hay alguna razón por la que quieras evitarlo?

    – Peter Lawrey

    17 de septiembre de 2012 a las 8:46

  • Solo para que conste y como explicación de por qué evitar el iterador: actualmente estoy enfrentando ese problema en un juego de Android escrito en Java. En este momento estoy usando un HashSet para almacenar oyentes que necesitan ser notificados regularmente sobre eventos. Sin embargo, iterar repetidamente las colecciones provoca una gran actividad del recolector de basura que puede sobrecargar el bucle del juego. Y eso es un no-go en un juego de Java. Voy a reescribir estas partes.

    – tiguchi

    28 de enero de 2013 a las 19:36

  • @thecoshman Estoy hablando solo desde una perspectiva de desarrollo de juegos Java en la que desea evitar GC durante las actualizaciones regulares del estado del juego a toda costa. Los iteradores son solo objetos útiles temporalmente, ya que no puede restablecerlos desde el principio, por lo tanto, se recrean en cada llamada al método de iteración (consulte la fuente ArrayList.java, por ejemplo). Si se usa en un bucle de juego para iterar objetos de escena y considerando al menos 30 actualizaciones por segundo, termina con al menos 60 (la escena generalmente se itera dos veces por ciclo) objetos iteradores por segundo en la memoria esperando GC. Eso tiene un gran impacto en Android.

    – tiguchi

    27/01/2014 a las 17:40

  • ¿Quizás uno debería elegir una estructura de datos más adecuada en ese caso? Un conjunto no está diseñado para iterar de manera eficiente. ¿Por qué no usar un ArrayList e iterarlo con un bucle for estándar? No se crean iteradores adicionales, el acceso de lectura es muy rápido.

    – stef77

    23 de julio de 2015 a las 7:45

avatar de usuario
asilias

Puedes usar un mejorado para bucle:

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

//populate set

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

O con Java 8:

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

  • Creo que esto usa un iterador detrás de escena.

    – munyengm

    17 de septiembre de 2012 a las 8:45

  • @munyengm Sí lo hace. No hay forma de iterar sobre un conjunto sin un iterador, además de acceder a la estructura subyacente que contiene los datos a través de la reflexión y replicar el código proporcionado por Set#iterator…

    – asilias

    17 de septiembre de 2012 a las 8:46


  • Esto funciona, pero si pudiera dar problemas, entonces no es la solución para mí. Supongo que no tengo elección, debo usar Iterator. Gracias por todo de todos modos.

    – usuario1621988

    17 de septiembre de 2012 a las 8:55

  • @ user1621988 ¿Qué problemas? No hay problemas con el código que proporcioné. Simplemente proporciona una manera agradable y limpia de iterar sobre un conjunto sin tener que usar explícitamente un iterador.

    – asilias

    17 de septiembre de 2012 a las 8:56


  • @assylias Esto podría generar confusión, ya que el título establece claramente que se repiten los elementos sin iterador. Podría agregar un poco de precaución aquí, ya que internamente usa el iterador solo, por lo que la solución solo proporciona una solución sintáctica, no la real.

    – AndroidEngineX

    8 de junio de 2021 a las 19:07

avatar de usuario
Benny Neugebauer

Hay al menos seis formas adicionales de iterar sobre un conjunto. Me son conocidas las siguientes:

Método 1

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

Método 2

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

Método 3

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

Método 4

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

Método 5

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

Método 6

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

Este es el HashSet que utilicé para mis ejemplos:

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

  • Hola @benny-neugebauer Por Método 4, Método 5, Método 6 simplemente puede eliminar redundantes stream().

    – Eugenio T.

    30 de octubre de 2017 a las 10:48

  • Sin mencionar que el Método 4, el Método 5 y el Método 6 son iguales.

    – Gustavo Cinque

    21 de septiembre de 2018 a las 11:28

avatar de usuario
Juvanis

Convirtiendo tu conjunto en una matriz
también puede ayudarlo a iterar sobre los elementos:

Object[] array = set.toArray();

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

  • Solo para que conste, toArray llama al iterador del conjunto.

    – asilias

    17 de septiembre de 2012 a las 8:51

avatar de usuario
Tharindu Rajarathna

Para demostrarlo, considere el siguiente conjunto, que contiene diferentes objetos 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));

Clase de modelo de persona

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. La declaración for tiene un formulario diseñado para la iteración a través de colecciones y arreglos. Este formulario a veces se denomina declaración for mejorada y se puede usar para hacer que sus bucles sean más compactos y fáciles de leer.
for(Person p:people){
  System.out.println(p.getName());
}
  1. Java 8 – java.lang.Iterable.forEach(Consumidor)
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

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

Throws: NullPointerException - if the specified action is null

Since: 1.8

avatar de usuario
samuel moshie

Puede usar la operación funcional para un código más ordenado

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

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

  • La llamada requiere API 24

    – djdance

    24 de enero de 2020 a las 9:38

Aquí hay algunos consejos sobre cómo iterar un conjunto junto con sus actuaciones:

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

El código se explica por sí mismo.

El resultado de las duraciones son:

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

podemos ver el Lambda lleva más tiempo Iterator es el más rápido

  • La llamada requiere API 24

    – djdance

    24 de enero de 2020 a las 9:38

Enumeración(?):

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

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

o

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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad