Necesito un Iterator<Character>
desde un objeto String
. ¿Hay alguna función disponible en Java que me proporcione esto o tengo que codificar la mía?Java: cómo obtener Iterator <Character> desde String
Respuesta
Una opción es utilizar Guava:
ImmutableList<Character> chars = Lists.charactersOf(someString);
UnmodifiableListIterator<Character> iter = chars.listIterator();
Esto produce una lista inmutable de caracteres que está respaldada por la cadena dada (sin copia involucrada).
Si termina haciéndolo usted mismo, recomendaría no exponer la clase de implementación para el Iterator
como lo hacen otros ejemplos. Me gustaría recomendar en lugar de hacer su propia clase de utilidad y la exposición de un método de fábrica estática:
public static Iterator<Character> stringIterator(final String string) {
// Ensure the error is found as soon as possible.
if (string == null)
throw new NullPointerException();
return new Iterator<Character>() {
private int index = 0;
public boolean hasNext() {
return index < string.length();
}
public Character next() {
/*
* Throw NoSuchElementException as defined by the Iterator contract,
* not IndexOutOfBoundsException.
*/
if (!hasNext())
throw new NoSuchElementException();
return string.charAt(index++);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
Gracias por la pista. Entonces, supongo que la respuesta a mi pregunta es "No". – Albert
@Albert: Sí, no creo que haya nada en la biblioteca estándar para hacer exactamente lo que quieres. Solo señalando que el código que hace lo que desea existe en una biblioteca sólida y bien probada. – ColinD
@Albert: Por supuesto, puede recorrer el String char-by-char en, por ejemplo, el bucle 'for' utilizando el método' String # toCharArray() '. – Esko
No estoy seguro si hay una manera más directa pero podría hacer algo como;
Arrays.asList(string.toCharArray()).iterator();
arañazos que; Arrays.asList no hace lo que parece recordar que hace.
Edición 2: Parece que trabajó por última vez de esta manera en 1.4
CharacterIterator it = new StringCharacterIterator("abcd");
// Iterate over the characters in the forward direction
for (char ch=it.first(); ch != CharacterIterator.DONE; ch=it.next())
// Iterate over the characters in the backward direction
for (char ch=it.last(); ch != CharacterIterator.DONE; ch=it.previous())
El Iterator iterar sobre una colección o lo pone en práctica. La clase de cadena no implementa esta interfaz. Entonces no hay una forma directa.
Para iterar sobre una cadena, primero tendrá que crear una matriz de caracteres a partir de ella y luego de esta colección de caracteres una Colección.
Es incorrecto decir que un 'iterador' solo itera sobre una colección. 'Iterator' es una interfaz simple que puede iterar sobre cualquier cosa que se implemente para iterar. – ColinD
+1 Tienes razón que solo me ha perdido. –
No existe, pero es trivial para aplicar:
class CharacterIterator implements Iterator<Character> {
private final String str;
private int pos = 0;
public CharacterIterator(String str) {
this.str = str;
}
public boolean hasNext() {
return pos < str.length();
}
public Character next() {
return str.charAt(pos++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
La aplicación es probablemente tan eficiente como se pone.
Respuesta corta: No, usted tiene que codificarlo.
Respuesta larga: lista y establece dos tienen un método para obtener un Iterator (hay algunas otras clases de colección, pero probablemente no es lo que buscas). Las interfaces List y Set son parte de Collections Framework que solo permiten agregar/eliminar/iterar Objetos como Carácter o Entero (no primitivos como char o int). Hay una función en Java 1.5 called auto-boxing que ocultará esta primitiva a la conversión de objeto, pero no la recomiendo y no proporcionará lo que desea en este caso.
Una alternativa sería la de envolver la cuerda en una clase de su propia que
implements Iterator<Character>
pero que podría ser más trabajo de lo que vale.
Aquí es un fragmento de código para hacer lo que quiere:
String s = "";
List<Character> list = new ArrayList<Character>(s.length());
for (int i = 0; i < s.length(); i++) {
// note that Character.valueOf() is preferred to new Character()
// you can omit the Character.valueOf() method
// and Java 1.5+ will auto-box the primitive into an Object
list.add(Character.valueOf(s.charAt(i)));
}
Iterator<Character> iterator = list.iterator();
'List' y' Set' están ** no ** implementando 'Iterator'. – whiskeysierra
Están implementando la interfaz 'Iterable' (que proporciona una función' iterator() 'que devuelve un' Iterator') para que esté bien. Pero su código es ineficiente porque crea una copia completa de la cadena. – Albert
@Willi, está en lo cierto, las interfaces List y Set son subinterfaces de Collection que contienen el método .interator(). Si observa de cerca esto se logra al extender clases abstractas que contienen subclases privadas que de hecho implementan Iterator, que itera sobre los datos dentro de la Lista o Conjunto. Debería haber indicado que tanto List como Set proporcionan un método para obtener un iterador. –
ninguna manera directa. No es difícil de codificar, sin embargo:
public static Iterator<Character> gimmeIterator(final String x) {
Iterator<Character> it = new Iterator<Character>() {
String str = x == null ? "" : x;
int pos = -1; // last read
public boolean hasNext() { return(pos+1 < str.length()); }
public Character next() { pos++; return str.charAt(pos); }
public void remove() {
throw new UnsupportedOperationException("remove unsupported for this iterator");
}
};
return it;
}
El robo de otra persona en otra respuesta, esta es probablemente la mejor aplicación directa (si no va a utilizar la guayaba).
/**
* @param string
* @return list of characters in the string
*/
public static List<Character> characters(final String string) {
return new AbstractList<Character>() {
@Override
public Character get(int index) {
return string.charAt(index);
}
@Override
public int size() {
return string.length();
}
};
}
for (char c : myString.toCharArray()) {
}
Eso funciona en dicho bucle, pero aún 'char []' no se puede asignar a 'Iterable
Además, como las cadenas son inmutables pero las matrices no lo son, debe crear una copia. – mhsmith
Esto se puede hacer con un poco de ayuda de Apache Commons Lang (si no desea utilizar la guayaba, y quieren un verdadero java.util.Iterator
.
private static Iterator<Character> iterator(String string) {
return Arrays.asList(ArrayUtils.toObject(string.toCharArray())).iterator();
}
con Java 8 o más nuevo puede usar la instalación de flujo. Con el método chars()
puede acceder a IntStream
. El IntStream
admite el método iterator()
que devuelve un iterador OfInt
. OfInt
implementa Iterator<Integer>
.
String str = "foobar";
OfInt ofit = str.chars().iterator();
Iterator<Integer> it = ofit;
No es una solución perfecta, ya que preguntas para iterador < Carácter >.
Por cierto: con str.codePoints() también puede acceder a un punto de código IntStream.
Menciona codePoints(). Un aspecto importante de codePoints() es que le permite tratar con caracteres sustitutos. Ver [esta respuesta] (http://stackoverflow.com/a/40444598/99717). –
Esto se siente sucio, pero se puede usar escáner con delimitador de cadena vacía:
Scanner scanner = new java.util.Scanner(myInput).useDelimiter("");
escáner implementa Iterator
, por lo scanner
es ahora un Iterator
de cadenas de longitud-1, que está cerca.
Continuar con la sucia, en Java 8 a continuación, puede hacer esto para iterar sucintamente por caracteres (muy?):
for (String s: (Iterable<String>)() -> scanner) {
char c = s.charAt(0);
System.out.println(c);
}
Para obtener más detalles sobre por qué () -> scanner
obras (y por qué puede ser peligroso, aunque no en este caso de uso), vea Explain how this lambda can be assigned to an Iterable.
- 1. String de Java desde InputStream
- 2. Tratar Enumeración <T> como Iterator <T>
- 3. Java Iterator Concurrency
- 4. Forma fácil de obtener una representación de cadena de Map <String, String []> en java?
- 5. Java: Enumeración del conjunto <String>
- 6. Cómo convertir Map <String, String> a Map <Long, String> usando guava
- 7. Cómo obtener valores distintos de dos Lista <string>?
- 8. JAXB para unmarshall <string> foobar</string>
- 9. ¿Cómo puedo convertir String [] para arrayList <String>
- 10. Cómo convertir clases en Dictionary <string, string>?
- 11. java HashMap clasificación <String, Entero>. ¿Cómo ordenarlo?
- 12. std :: list iterator: obtener el siguiente elemento
- 13. Map <String, String> JSON en
- 14. Cómo convertir Dictionary <string, object> a Dictionary <string, string> en C#
- 15. JPA Map <String, String> mapping
- 16. ¿Por qué usar string :: iterator en lugar de index?
- 17. IDictionary <string, string> versus Dictionary <string, string>
- 18. Java: Obtener URI desde FilePath
- 19. Java: ¿cómo inicializar String []?
- 20. ¿Cómo obtener datos de la lista <Object> (Java)?
- 21. Uso FlurryAgent.onEvent (String EVENTID, mapa <String, String> Parámetros)
- 22. ¿Cómo obtener un Iterator [Node] de transmisión desde un documento XML grande?
- 23. StringDictionary vs Dictionary <string, string>
- 24. casting ArrayList <String> a String []
- 25. Por qué java.util.Properties implementa Map <Object, Object> y no Map <String, String>
- 26. Convertir <String> a cadena delimitada
- 27. Java String Valor Unicode
- 28. LINQ - Lista de giros en <string> Dictionary <string, string>
- 29. Diferencia entre Java Enumeration y Iterator
- 30. Haga nuestra propia lista <string, string, string>
Véase también http://stackoverflow.com/questions/1527856/how-can-i-iterate-through-the-unicode-codepoints-of-a-java-string – rogerdpack