streams - Java 8/9: ¿Se puede asignar un carácter en una cadena a sus índices(usando flujos)?
lambdas y streams (4)
Dada una String s
y un char c
, tengo curiosidad si existe algún método para producir una List<Integer> list
desde s
(donde los elementos dentro de la list
representan los índices de c
dentro de s
).
Un acercamiento cercano, pero incorrecto sería:
public static List<Integer> getIndexList(String s, char c) {
return s.chars()
.mapToObj(i -> (char) i)
.filter(ch -> ch == c)
.map(s::indexOf) // Will obviously return the first index every time.
.collect(Collectors.toList());
}
Las siguientes entradas deben producir la siguiente salida:
getIndexList("Hello world!", ''l'') -> [2, 3, 9]
... o en java-9:
Stream.of("Hello world!")
.map(Scanner::new)
.flatMap(s -> s.findAll("l"))
.map(mr -> mr.start())
.forEach(System.out::println);
Se puede hacer con IntStream
public static List<Integer> getIndexList(String s, char c) {
return IntStream.range(0, s.length())
.filter(index -> s.charAt(index) == c)
.boxed()
.collect(Collectors.toList());
}
Una alternativa en Java9 podría ser utilizar la iterate(int seed, IntPredicate hasNext,IntUnaryOperator next)
siguiente manera:
private static List<Integer> getIndexList(String word, char c) {
return IntStream
.iterate(word.indexOf(c), index -> index >= 0, index -> word.indexOf(c, index + 1))
.boxed()
.collect(Collectors.toList());
}
Utilizando Java 9, puede buscar de forma iterativa utilizando el último índice como punto de partida, y detenerse cuando no se encuentre ninguna coincidencia:
public static List<Integer> getIndexList(String s, char c) {
return IntStream.iterate(s.indexOf(c), i -> s.indexOf(c, i + 1))
.takeWhile(i -> i > -1)
.boxed()
.collect(Collectors.toList());
}
Descargo de responsabilidad: no he probado esto.