有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么在Guava filter/transform函数中有时返回可修改的视图,而有些返回不可修改的视图?

例如,所有列表、集合2、集合返回可修改的视图-从视图集合中删除将删除原始项

这很好:

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();

当我使用Iterables和Iterators方法filter/transform时,我得到了一个可修改的视图(即所有这些代码重用不可修改的iterator)

这不管用:

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());

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

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


共 (1) 个答案

  1. # 1 楼答案

    Iterators.transform(扩展为Iterables.transform)确实支持remove()。从其Javadoc:

    The returned iterator supports remove() if the provided iterator does.

    然而Iterators.filter没有。这是因为过滤迭代器无法在不调用底层迭代器上的next()的情况下实现hasNext()。在基础迭代器上调用hasNext()是不够的,因为该迭代器中的下一个元素(以及之后的每个元素,可能)可能与Predicate不匹配

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

    过滤的CollectionIterator有完全相同的问题(实际上,它是使用Iterators.filter创建的)。clear()removeAll方法之所以有效,是因为它们完全控制迭代器(它们都是使用Iterables.removeIf实现的)