问题描述
我想使用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
时,最大的挑战是为两个方法hasNext
和next
提供正确的语义,而不保证调用方如何调用它们,即,您不能假定它不会再调用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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!