如何根据谓词过滤Iterable? [英] How can I filter an Iterable based upon a Predicate?

查看:52
本文介绍了如何根据谓词过滤Iterable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Iterable<String>和谓词来选择要保留的字符串,以进行字符串列表过滤,其他字符串必须从列表中删除,但是我并没有低估我如何进行删除.

I want to do a string list filter function using an Iterable<String> and a predicate to select the strings to keep, the other ones must be removed from the list, but I'm not understating how I do the remove.

static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
    for (T s: it) {
        if (pred.test(s)==false) {
            // what to do here?
        }
    }
    return ...;
}

对于此输入:

{"a","","b",""}

我希望

{"a","b"}

推荐答案

Iterable表示根据请求提供Iterator的功能.因此,要使用过滤逻辑装饰现有的可迭代对象,必须实现装饰Iterator.

An Iterable represents the capability to provide an Iterator on request. So, to decorate an existing iterable with a filtering logic, you have to implement the decorating Iterator.

static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
    return () -> new Iterator<T>() {
        Iterator<T> sourceIterator = it.iterator();
        T current;
        boolean hasCurrent;

        @Override
        public boolean hasNext() {
            while(!hasCurrent) {
                if(!sourceIterator.hasNext()) {
                    return false;
                }
                T next = sourceIterator.next();
                if(pred.test(next)) {
                    current = next;
                    hasCurrent = true;
                }
            }
            return true;
        }

        @Override
        public T next() {
            if(!hasNext()) throw new NoSuchElementException();
            T next = current;
            current = null;
            hasCurrent = false;
            return next;
        }
    };
}

您可以通过

List<String> original = new ArrayList<>();
Collections.addAll(original, "foo", "bar", "baz");
Iterable<String> filter = select(original, s -> s.startsWith("b"));
System.out.println(String.join(", ", filter));
original.removeIf(s -> !s.endsWith("r"));
System.out.println(String.join(", ", filter));

实现这样的Iterator时,最大的挑战是为两个方法hasNextnext提供正确的语义,而不保证调用方如何调用它们,即,您不能假定它不会再调用hasNext()两次,也不会总是用前面的hasNext()调用next().

The biggest challenge when implementing such an Iterator, is to provide the two methods hasNext and next with the correct semantics, without any guaranty regarding how the caller will invoke them, i.e. you can not assume that it will never invoke hasNext() twice nor that next() will always be invoked with a preceding hasNext().

使用Stream API可以更轻松地实现相同的逻辑:

The same logic can be implemented much easier using the Stream API:

static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
    return () -> StreamSupport.stream(it.spliterator(), false)
        .filter(pred).iterator();
}

这篇关于如何根据谓词过滤Iterable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆