It all started when I noticed that removing elements from an a collection using removeElement() didn't actually remove them from the database. While debugging that issue, I found that using remove() worked as expected, so I took a look at ArrayCollection#removeElement() and remove(). I remained thorougly confused for a good 5 minutes because the two methods are virtually identical, yet they were behaving differently. That's when I realized that loading a collection from the database gives you a PersistentCollection, not an ArrayCollection.
So here's the bug: PersistentCollection#remove() and PersistentCollection#removeElement() behave differently. remove() marks the collection as changed only if an element is actually removed, then schedules an OrphanRemoval if applicable. removeElement() unconditionally marks the collection as changed and forgets to check for orphanRemoval.
Since both methods are virtually identical, I suggest that they are refactored to use a common code path instead of duplicating their code. The same should be done with ArrayCollection.