如何将Predicate动态添加到List中

How to dynamically add Predicate into List

Java有什么办法可以动态添加Predicate到List中吗?为了简要说明,我是这样做的:

List<Predicate<String>> filters = Arrays.asList(
    t -> !Utilities.isNumeric(t)
);
filters.add(t -> !t.isEmpty());

但是执行 filters.add 会导致 UnsupportedOperationException。这样的固定列表很好。

List<Predicate<String>> filters = Arrays.asList(
    t -> !Utilities.isNumeric(t),
    t -> !t.isEmpty()
);

解决方案:

List<Predicate<String>> filters = new ArrayList<>(Arrays.asList(
    t -> !Utilities.isNumeric(t)
));

解释:

Arrays.asList returns 数组参数的固定长度列表1 包装器。由于它是固定大小的,因此会更改大小的方法会抛出 UnsupportedOperationException.

通过将其提供给 ArrayList 构造函数,您可以创建一个新列表,其大小可以更改。


1 - .... 但列表 不是一成不变的 。可以通过更新支持数组或使用 List::set(int, T) 方法对其进行修改。

这里的问题是 Arrays.asList 创建了一个固定大小的列表:您不能添加到使用此方法获得的列表中。

您必须创建一个可变列表,例如使用 new ArrayList():

List<Predicate<String>> filters = new ArrayList<>(Arrays.asList(
  t -> !Utilities.isNumeric(t)
));
filters.add(t -> !t.isEmpty());

会起作用,因为 filters 列表是可变的。

Arrays.asList() returns 列表的 固定 实例:

Returns a fixed-size list backed by the specified array.

当您 "manually" 写下一系列事物时,它的意思是 "shortcut"。一个 "fixed size" 清单,要准确。这意味着您可以 "replace" 个元素,但不能添加或删除条目。

因此只需将该调用的结果用作创建另一个列表的输入,例如:new ArrayList<>(Arrays.asList(...)

以防万一您需要将 Predicate 应用于某些输入,您可以将它们链接起来。唯一的缺点是涉及大量转换 - 因为 lambda 表达式和方法引用是多边形表达式...

Predicate<String> both = ((Predicate<String>) Utilities::isNumeric).negate()
                             .and(((Predicate<String>) String::isEmpty).negate());