Вот сводка требований для removeAll
(и любого другого вида обработки на стороне сервера, например executeOnKey
et c):
- Ключ и значение должны быть сериализуемыми, а их классы должны быть доступны на сервере classpath
Predicate
(или EntryProcessor
et c) должны быть сериализуемыми и доступны на сервере classpath
Я предполагаю, что в вашем случае BiPredicate<K, C> removeCondition
не сериализуем; однако он должен быть сериализован как часть лямбды, которую вы передаете removeAll
. Например, рассмотрим этот код:
class Scratch {
public static void main(String[] args) {
remove((x, y) -> true);
}
private static void remove(BiPredicate<String, String> predicate) {
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
// put 100 items in the map
IMap<String, String> map = hz.getMap("map");
for (int i = 0; i < 100; i++) {
map.put("" + i, "" + i);
}
map.removeAll((Predicate<String, String> & Serializable)
entry -> predicate.test(entry.getKey(), entry.getValue()));
// now size is 0
System.out.println("Map size after removeAll " + map.size());
}
}
Приведенный выше код будет выполнен без каких-либо проблем. Как только вы добавите еще один HazelcastInstance
в кластер (просто добавьте Hazelcast.newHazelcastInstance()
в remove
тело метода), экземпляр Predicate
должен быть сериализован и отправлен по сети между двумя членами кластера. Это терпит неудачу, потому что аргумент predicate
не является Serializable
, но является частью лямбды Predicate
, передаваемой в качестве аргумента removeAll
. Решение состоит в том, чтобы убедиться, что все ссылки в вашей лямбде являются сериализуемыми. Таким образом, в приведенном выше примере исправление заключается в обновлении метода main
следующим образом:
public static void main(String[] args) {
remove((BiPredicate<String, String> & Serializable) (x, y) -> true);
}
В общем, соблюдайте осторожность при использовании лямбда-выражений, потому что легко случайно захватить поля внешнего класса и в этом случае вам нужно будет обратиться к сериализуемости содержащего класса, и размер сериализованной формы вашей лямбды неожиданно увеличится. Цитирование https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#serialization "Вы можете сериализовать лямбда-выражение, если его целевой тип и захваченные аргументы сериализуемы. Однако, как и для внутренних классов, сериализация лямбда-выражений настоятельно не рекомендуется."