Java 8/9: Может ли символ в String сопоставляться с его индексами (используя потоки)?
Учитывая String s
и char c
, мне любопытно, существует ли какой-либо метод создания List<Integer> list
из s
(где элементы в list
представляют индексы c
в s
).
Близким, но неправильным подходом было бы:
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());
}
Следующие входы должны давать следующий результат:
getIndexList("Hello world!", 'l') -> [2, 3, 9]
Ответы
Ответ 1
Может быть сделано с 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());
}
Ответ 2
Используя Java 9, вы можете итеративно искать с использованием последнего индекса в качестве начальной точки и останавливаться, если совпадение не найдено:
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());
}
Отказ от ответственности: я не проверял это.
Ответ 3
Альтернативой Java9 может быть использование iterate(int seed, IntPredicate hasNext,IntUnaryOperator next)
следующим образом:
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());
}
Ответ 4
... Или в java-9:
Stream.of("Hello world!")
.map(Scanner::new)
.flatMap(s -> s.findAll("l"))
.map(mr -> mr.start())
.forEach(System.out::println);