我理解为什么我不能在jpa返回的集合上使用removeIf()但我可以使用迭代器来解决这个问题。
id
答案 0 :(得分:6)
这种奇怪行为的典型原因是你有hashCode(和equals)的自定义实现。如果在这种情况下您更改了对象并导致hashCode不同,那么使用JDK集合即使使用iterator.remove()也无法从Set中删除该对象。 JDK集合通过重新计算hashCode并使用该哈希执行对象的删除来实现删除。如果散列已经更改,则删除失败并且JDK实现会忽略它,尽管它们会因为删除而返回true,这意味着集合实际上已经改变了甚至很难实现。悲伤却又是真的。
答案 1 :(得分:0)
完美,另一条路是抛出一个新列表来解决问题......例如:
if (!CollectionUtils.isEmpty(getEvento().getAtividade())) {
Set<Atividade> listAtividade = getEvento().getAtividade();
getEvento().setAtividade(new HashSet<>());
getEvento().getAtividade().addAll(listAtividade);
}
getEvento().getAtividade().removeIf(a ->
a.getEspecialidade().getId().equals(especialidade.getId()));
or
getEvento().getAtividade().removeAll(getListAtividadeNotSelected());
答案 2 :(得分:0)
实际答案很可能既不是Equals / Hash
(请与@EqualsAndHashCode
一起使用Lombok),也不是创建新列表(只是隐藏实际问题)。
实际上,很有可能使用Arrays.asList
或Collections.singletonList
来创建不可变的ArrayList
。
假设您在JPA中有一个OneToMany / ManyToMany关系,那么一个Collection-让它成为具有成员的Group。组/用户都是正确的JAP @Entity
var user1 = new User();
var user2 = new User();
var group = new Group();
group.addMembers(Arrays.asList(user1,user2));
group = groupRepository.save(group);
// will throw an exception
group.getMembers().removeIf((user) user.getId() == 1);
原因是Arrays.asList(user1,user2)
创建了一个具有固定固定大小的实际不可变数组。在其上运行remove会失败,并显示OperationNotSupport
。
由于Arryas.asList
和Collections.singletonList
总是很笨拙(因为您必须为1+选择前者,而对于1个元素则选择后者),并且在这两种情况下,您都可以使用您可能不知道的不可变数组,可以使用番石榴
Lists.newArrayList(user1,user2);
Lists.newArrayList(user1);
适用于任何大小,并且该数组是可变的。
请注意,如果您使用JPA工具,此问题可能会更加隐蔽,因为它期望列表可变,并且如果操作不当,则可以通过更多的加密异常处理您。