开发者

Why in Guava filter/transform functions sometimes return modifiable view and some returns unmodifiable view?

For example all Lists, Collections2, Sets return a modifiable view - removing from view collection will remove original items.

This works fine:

List<Integer> list = Lists.ne开发者_运维问答wArrayList(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();

When I use Iterables and Iterators methods filter/transform I get umodifiable view (i.e all this code reuse UnmodifibleIterator).

This doesn't work:

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

I can't find any semantic difference between Iterable and Collection/List/Set/Map so why there are so different implementations in Guava?

The other strange behavior is that the iterator in the first case still doesn't allow the remove operation, but clear or remove/removeAll works fine.


Iterators.transform (and Iterables.transform, by extension) does support remove(). From its Javadoc:

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

Iterators.filter, however, does not. The reason for this is that there is no way for a filtered iterator to implement hasNext() without calling next() on the underlying iterator. Calling hasNext() on the underlying iterator is not enough, because the next element in that iterator (and every one after that as well, possibly) may not match the Predicate.

The problem, then, is that calling hasNext() on the filtered iterator must advance the position of the underlying iterator. This prevents a subsequent call to remove() from removing the element that was returned by the most recent call to next() (which is part of the contract of remove()). Thus, remove() cannot be supported on a filtered iterator.

The Iterator for a filtered Collection has the exact same issue (in fact, it's created using Iterators.filter). The clear() and removeAll methods work because they have full control over the iterator (they are both implemented using Iterables.removeIf).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜