来自带有 next() 和 get() 的对象的迭代器

Iterator from object with next() and get()

给定这样一个对象:

Matcher matcher = pattern.matcher(sql);

像这样使用:

Set<String> matches = new HashSet<>();
while (matcher.find()) {
    matches.add(matcher.group());
}

我想用更面向对象的东西替换这个 while 循环:

new Iterator<String>() {
    @Override
    public boolean hasNext() {
        return matcher.find();
    }

    @Override
    public String next() {
        return matcher.group();
    }
}

这样我就可以很容易地,例如制作匹配流,坚持使用流畅的 API 等。

问题是,我不知道也找不到更简洁的方法来创建此 Stream 或 Iterator。像上面这样的匿名 class 对我来说太冗长了。

我曾希望在 jdk 中找到 IteratorFactory.from(matcher::find, matcher::group)StreamSupport.of(matcher::find, matcher::group) 之类的东西,但到目前为止还没有成功。我毫不怀疑像 apache commons 或 guava 这样的库为此提供了一些东西,但假设我不能使用它们。

在 jdk 中是否有方便的流或迭代器工厂采用 hasNext/next 方法组合?

在 java-9 中,您可以通过以下方式完成:

Set<String> result = matcher.results()
            .map(MatchResult::group)
            .collect(Collectors.toSet());
System.out.println(result);

在 java-8 中你需要一个后端口,取自

编辑

顺便说一句,有一种方法 tryAdvance 可以合并 find/group,像这样:

static class MyIterator extends AbstractSpliterator<String> {

    private Matcher matcher;

    public MyIterator(Matcher matcher) {
        // I can't think of a better way to estimate the size here
        // may be you can figure a better one here
        super(matcher.regionEnd() - matcher.regionStart(), 0);
        this.matcher = matcher;
    }

    @Override
    public boolean tryAdvance(Consumer<? super String> action) {
        while (matcher.find()) {
            action.accept(matcher.group());
            return true;
        }

        return false;
    }
}

用法举例:

Pattern p = Pattern.compile("\d");
Matcher m = p.matcher("12345");
Set<String> result = StreamSupport.stream(new MyIterator(m), false)
            .collect(Collectors.toSet());

我写的这个class体现了我想在jdk中找到的东西。显然它只是不存在。 提供了 java 9 流解决方案。

public static class SearchingIterator<T> implements Iterator<T> {
    private final BooleanSupplier advancer;
    private final Supplier<T> getter;

    private Optional<T> next;

    public SearchingIterator(BooleanSupplier advancer, Supplier<T> getter) {
        this.advancer = advancer;
        this.getter = getter;

        search();
    }

    private void search() {
        boolean hasNext = advancer.getAsBoolean();
        next = hasNext ? Optional.of(getter.get()) : Optional.empty();
    }

    @Override
    public boolean hasNext() {
        return next.isPresent();
    }

    @Override
    public T next() {
        T current = next.orElseThrow(IllegalStateException::new);
        search();
        return current;
    }
}

用法:

Matcher matcher = Pattern.compile("\d").matcher("123");
Iterator<String> it = new SearchingIterator<>(matcher::find, matcher::group);