¿Cómo puedo iterar sobre un Set
/HashSet
sin lo siguiente?
Iterator iter = set.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
usuario1621988
¿Cómo puedo iterar sobre un Set
/HashSet
sin lo siguiente?
Iterator iter = set.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
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
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
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
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
}
for(Person p:people){ System.out.println(p.getName()); }
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
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);
});
¿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