4 回答

TA貢獻1829條經(jīng)驗 獲得超6個贊
AnIterable代表提供Iterator應(yīng)要求的能力。因此,要使用過濾邏輯裝飾現(xiàn)有的可迭代對象,您必須實現(xiàn) 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));
實現(xiàn)這樣的 , 時最大的挑戰(zhàn)Iterator是提供兩種方法hasNext和next正確的語義,而不保證調(diào)用者將如何調(diào)用它們,即你不能假設(shè)它永遠不會調(diào)用hasNext()兩次,也next()不會總是被調(diào)用之前hasNext()。
使用 Stream API 可以更輕松地實現(xiàn)相同的邏輯:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return () -> StreamSupport.stream(it.spliterator(), false)
.filter(pred).iterator();
}

TA貢獻1775條經(jīng)驗 獲得超11個贊
由于 anyCollection是Iterable,只需將符合條件的項目添加到新集合中并稍后返回:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
Collection<T> collection = new ArrayList<>();
for (T s: it) {
if (!pred.test(s)) {
collection.add(s);
}
}
return collection;
}
幾點見解:
pred.test(s)==false表達式應(yīng)簡化為!pred.test(s)
可以使用以下方法縮短方法的全部內(nèi)容java流通過這種方式:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return StreamSupport.stream(it.spliterator(), false)
.filter(pred)
.collect(Collectors.toList());
}

TA貢獻1796條經(jīng)驗 獲得超4個贊
首先把你包裝Iterable<T>
成Stream<T>
:
純Java:
StreamSupport.stream(it.spliterator(), false)
Streams.stream(it)
StreamEx.of(it.iterator())
然后按您的過濾Predicate<T>
:
... stream.filter(pred.negate()) ...
最后返回Iterable<T>
:
作為
lambda
:return () -> stream.iterator();
作為
method reference
return stream::iterator;
完整示例:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return StreamSupport.stream(it.spliterator(), false).filter(pred.negate())::iterator;
}
要么:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
Stream<T> stream = stream(it.spliterator(), false);
Predicate<T> negatedPred = pred.negate();
Stream<T> filteredStream = stream.filter(negatedPred);
return filteredStream::iterator;
}

TA貢獻1858條經(jīng)驗 獲得超8個贊
我在評論中提到的 Holger 的替代解決方案如下所示:
static <T> Iterable<T> select(Iterable<T> toIterate, Predicate<T> pred) {
return () -> new Iterator<T>() {
Iterator<T> delegate = toIterate.iterator();
T next = findNextValid();
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null) throw new NoSuchElementException();
T result = next;
next = findNextValid();
return result;
}
private T findNextValid() {
T result = null;
while (result == null && delegate.hasNext()) {
T candidate = delegate.next();
if (pred.test(candidate)) {
result = candidate;
}
}
return result;
}
};
}
不同之處在于,不需要額外的標(biāo)記hasCurrent,它會Iterator在實際請求下一個元素之前提前。你可能認為后者是不可取的。
添加回答
舉報