Collections 使用next()和get()从对象进行迭代器

Collections 使用next()和get()从对象进行迭代器,collections,java-8,iterator,factory,fluent,Collections,Java 8,Iterator,Factory,Fluent,给定这样一个对象: Matcher matcher = pattern.matcher(sql); static class MyIterator extends AbstractSpliterator<String> { private Matcher matcher; public MyIterator(Matcher matcher) { // I can't think of a better way to estimate the si

给定这样一个对象:

Matcher matcher = pattern.matcher(sql);
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;
    }
}
用这样的用法:

Set<String> matches = new HashSet<>();
while (matcher.find()) {
    matches.add(matcher.group());
}
Set 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();
    }
}
新迭代器(){
@凌驾
公共布尔hasNext(){
返回matcher.find();
}
@凌驾
公共字符串next(){
返回matcher.group();
}
}
因此,我可以轻松地进行匹配,坚持使用流畅的API等

问题是,我不知道,也找不到更简洁的方法来创建这个流或迭代器。像上面这样的匿名类对我来说太冗长了

我曾希望在jdk中找到类似(
IteratorFactory.from(matcher::find,matcher::group)
或(
StreamSupport.of(matcher::find,matcher::group)
)的东西,但到目前为止运气不好。我毫不怀疑ApacheCommons或guava之类的库为此提供了一些功能,但假设我不能使用它们


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

在java-9中,您可以通过以下方式实现:

Set<String> result = matcher.results()
            .map(MatchResult::group)
            .collect(Collectors.toSet());
System.out.println(result);
和用法,例如:

Pattern p = Pattern.compile("\\d");
Matcher m = p.matcher("12345");
Set<String> result = StreamSupport.stream(new MyIterator(m), false)
            .collect(Collectors.toSet());
Pattern p=Pattern.compile(\\d”);
匹配器m=p.Matcher(“12345”);
Set result=StreamSupport.stream(新的MyIterator(m),false)
.collect(收集器.toSet());

我编写的这个类体现了我希望在jdk中找到的内容。显然,它根本不存在。但提供了Java9流解决方案

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;
    }
}
公共静态类SearchingIterator实现迭代器{
私人最终布尔供应商预付款;
私人最终供应商getter;
私有可选下一步;
公共搜索迭代器(booleansupplieradvancer、suppliergetter){
this.advancer=advancer;
this.getter=getter;
搜索();
}
私有无效搜索(){
boolean hasNext=advancer.getAsBoolean();
next=hasNext?Optional.of(getter.get()):Optional.empty();
}
@凌驾
公共布尔hasNext(){
返回next.isPresent();
}
@凌驾
公共交通工具{
T current=next.orelsetrow(IllegalStateException::new);
搜索();
回流;
}
}
用法:

Matcher matcher = Pattern.compile("\\d").matcher("123");
Iterator<String> it = new SearchingIterator<>(matcher::find, matcher::group);
Matcher Matcher=Pattern.compile(\\d”).Matcher(“123”);
迭代器it=新搜索迭代器(matcher::find,matcher::group);

java-9是一个选项吗?旁注:您的两种方法实现都是错误的。它们仅在调用方总是调用
hasNext()
一次,后跟
next()
时才起作用。没有其他访问模式可以工作。从逻辑上讲,必须在
next()
方法中执行
find()
方法,因为这是进入下一个结果的过程。@JoachimSauer没有错。只要您以通常的hasNext()->next()方式使用此迭代器,它就可以正常工作。多次调用hasNext()会把事情搞砸,是的,但在我的情况下不会发生这种情况,所以没关系。@Marnes:我仍然会在代码评审中将其标记为一个问题,因为它在当前代码中工作并不意味着当代码的使用得到扩展时人们会考虑检查它。只需在一个地方实现一次转换,并确保正确实现该
匹配运算符
。但这当然是个人的选择。@JoachimSauer是的,我明白你的意思,理论上,如果你想要一切都完美,那是行不通的,但在我的问题中……当然!为什么我会感到惊讶,在搜索了这样一个拆分器后,霍尔格已经完成了,更感谢他的努力,但这两个都不是我真正的解决方案。我使用的是Java8,我希望避免为它滚动大的自定义代码块。如果jdk中没有现成的,那就太糟糕了。
matcher.regionEnd()-matcher.regionStart()
是一个不错的估计,因为它表示可能匹配的最大数量。@Marnes那么20行以下的代码是大的?我打赌你的项目中有其他JAR,你使用的JAR代码不到它们代码的2%,而且我打赌你确实有一个
util
包。。。尽管如此,您的选择确实是正确的。因为Java9流的答案,您接受了。我想我不能吃我想要的蛋糕。谢谢