如果我有ArrayList<Double> dblList
和Predicate<Double> IS_EVEN
,我可以使用以下内容从dblList
删除所有偶数元素:
Collections2.filter(dblList, IS_EVEN).clear()
如果dblList
是
dblList = Lists.transform(intList, TO_DOUBLE)
这不再起作用,因为转换后的列表是不可变的: - )
任何解决方案?
答案 0 :(得分:2)
Lists.transform()接受一个List并帮助返回RandomAccess列表的结果。 Iterables.transform()只接受Iterable,结果不是RandomAccess。最后,Iterables.removeIf(并且据我所知,这是Iterables中唯一的一个)在给定参数是RandomAccess的情况下进行优化,其中的一点是使算法线性而不是二次,例如想想如果你有一个很大的ArrayList(而不是一个应该更受欢迎的ArrayDeque)会发生什么,并且不断从它的开始移除元素直到它为空。
但是优化不依赖于迭代器remove(),而是依赖于List.set(),这在转换后的列表中是不可能的。如果要解决这个问题,我们需要另一个标记界面来表示“可选的set()实际上有效”。
所以你有的选择是:
答案 1 :(得分:1)
以下方法应该有效,但我还没有尝试过。
Collection<Double> dblCollection =
Collections.checkedCollection(dblList, Double.class);
Collections2.filter(dblCollection, IS_EVEN).clear();
checkCollection()方法生成未实现List的列表视图。 [相反,创建一个ForwardingCollection会更干净,但更冗长。]然后Collections2.filter()不会调用不支持的set()方法。
库代码可以更强大。 Iterables.removeIf()可以生成一个组合谓词,正如迈克尔D建议的那样,当传递一个转换后的列表时。但是,我们之前决定不通过添加那种特殊情况逻辑来使代码复杂化。
答案 2 :(得分:0)
也许:
Collection<Double> odds = Collections2.filter(dblList, Predicates.not(IS_EVEN));
或
dblList = Lists.newArrayList(Lists.transform(intList, TO_DOUBLE));
Collections2.filter(dblList, IS_EVEN).clear();
答案 3 :(得分:0)
只要您不需要中间集合,就可以使用Predicates.compose()创建首先转换项目的谓词,然后计算转换项目的谓词。
例如,假设我有一个List&lt; Double&gt;从中我想删除整数部分均匀的所有项目。我已经有一个函数&lt; Double,Integer&gt;这给了我整数部分和一个谓词&lt;整数&gt;告诉我它是否均匀。
我可以使用它们来获取新的谓词INTEGER_PART_IS_EVEN
Predicate<Double> INTEGER_PART_IS_EVEN = Predicates.compose(IS_EVEN, DOUBLE_TO_INTEGER);
Collections2.filter(dblList, INTEGER_PART_IS_EVEN).clear();
答案 4 :(得分:0)
经过一些尝试,我想我已经找到了它。)
final ArrayList<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5);
Iterables.removeIf(Iterables.transform(ints, intoDouble()), even());
System.out.println(ints);
[1,3,5]
答案 5 :(得分:0)
我没有解决方案,而是Iterables.removeIf()
与Lists.TransformingRandomAccessList
结合使用时发现某种问题。
转换后的列表实现RandomAccess,因此Iterables.removeIf()
委托给Iterables.removeIfFromRandomAccessList()
,这取决于不受支持的List.set()操作。
然而,调用Iterators.removeIf()
会成功,因为Lists.TransformingRandomAccessList
支持remove()操作。
见:Iterables:147
结论:instanceof RandomAccess不保证List.set()。
增加: 在特殊情况下,调用removeIfFromRandomAccessList()甚至可以工作: 当且仅当要擦除的元素在List的尾部形成一个紧凑的组或所有元素都被谓词覆盖。