为什么Guava过滤器/转换函数有时返回可修改的视图,有些返回不可修改的视图?

yur*_*ura 7 java guava

例如,所有Lists,Collections2,Sets都返回一个可修改的视图 - 从视图集合中删除将删除原始项目.

这很好用:

List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, -1, -2, -3, -4);    
Collection<Integer> transform = Collections2.filter(
    list, new Predicate<Integer>() {
        public boolean apply(Integer input) {
            return input.intValue() > 0;
        }
    });
transform.clear();
Run Code Online (Sandbox Code Playgroud)

当我使用Iterables和Iterators方法过滤/转换时,我得到umodifiable视图(即所有这些代码重用UnmodifibleIterator).

这不起作用:

List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, -1, -2, -3, -4);
Iterable<Integer> transform = Iterables.filter(
    list, new Predicate<Integer>() {
        public boolean apply(Integer input) {
            return input.intValue() > 0;
        }
    });
Iterables.removeIf(transform, Predicates.<Object>alwaysTrue());
Run Code Online (Sandbox Code Playgroud)

我找不到Iterable和Collection/List/Set/Map之间的任何语义差异,那么为什么Guava中有如此不同的实现呢?

另一个奇怪的行为是第一种情况下的迭代器仍然不允许删除操作,但清除或删除/ removeAll工作正常.

Col*_*inD 10

Iterators.transform(并且Iterables.transform,通过扩展)确实支持remove().来自它的Javadoc:

返回的迭代器支持remove()所提供的迭代器.

Iterators.filter但是,没有.这样做的原因是,如果hasNext()不调用next()底层迭代器,就无法实现过滤迭代器.调用hasNext()底层迭代器是不够的,因为迭代器中的下一个元素(以及之后的每个元素,可能)都不匹配Predicate.

那么问题是调用hasNext()过滤的迭代器必须提升底层迭代器的位置.这可以防止后续调用remove()删除最近一次调用返回的元素next()(这是合同的一部分remove()).因此,remove()在过滤的迭代器上不能支持.

Iterator用于过滤Collection具有完全相同的问题(事实上,它的使用产生Iterators.filter).该clear()removeAll方法的工作,因为他们对迭代器(它们都使用实行全面控制Iterables.removeIf).