If there is appetite to finish the COLLECTIONS-567 work, I created: https://github.com/apache/commons-collections/pull/703
This would allow the entire Bag hierarchy to be eventually deprecated/removed with a clear migration path but I didn't add any deprecations as part of that PR. Cheers, Paul. On Sun, Jul 5, 2026 at 8:41 AM Paul King <[email protected]> wrote: > > AI's read: > > Subject: Re: Why do we have both Bag and MultiSet? > > Peter's guess is right, and there's no need to speculate — the history > is recorded in COLLECTIONS-567 [1], filed by Thomas himself in 2015. > Before 4.0 there was discussion about fixing Bag's Collection-contract > violations in place, but it was kept as-is to ease migration of older > code bases. MultiSet was then added in 4.1 as the compliant > alternative, with the stated intent that "the old Bag could then be > deprecated". So having both was a deliberate transition strategy; > the deprecation step just never happened. > > They're also not quite two names for the same thing as the code > stands. Bag deviates from Collection in four places (add() sometimes > returns false after changing the collection, remove() removes all > occurrences, and containsAll/removeAll/retainAll respect cardinality), > while MultiSet keeps the inherited methods compliant and moves the > cardinality-aware operations to explicit ones (getCount, add(E, int), > remove(Object, int), setCount). > > For what it's worth, the rest of the ecosystem converged on the > MultiSet design. Guava's Multiset keeps every Collection method > contract-compliant and offers Multisets.containsOccurrences/ > removeOccurrences/retainOccurrences for the cardinality-sensitive > variants. Eclipse Collections is the interesting data point: it kept > the *name* Bag but not the semantics — its MutableBag extends > java.util.Collection, follows the standard contract, and puts > occurrence logic in dedicated methods (occurrencesOf, addOccurrences, > removeOccurrences, ...). So the naming isn't really the issue; the > contract is, and Bag's own javadoc warning ("Exercise caution when > using a bag as a Collection") is effectively an admission that it > can't safely be used as the type it declares. > > If there's appetite to finish what COLLECTIONS-567 started, two gaps > would need closing first: > > * There's no sorted MultiSet. Bag has SortedBag/TreeBag, but the > multiset package only contains HashMultiSet plus decorators, so > TreeBag users currently have nowhere to migrate. > * A migration note mapping the old semantics to explicit calls > (e.g. bag.remove(x) -> multiSet.setCount(x, 0)), and possibly > MultiSetUtils equivalents of Guava's occurrence-aware helpers, > which would preserve the one useful thing Bag's violations > provided, under honest names. > > A possible sequence: add SortedMultiSet/TreeMultiSet and the helpers > in a 4.x minor, cross-reference MultiSet from the Bag javadoc now, > deprecate Bag in a following minor, and remove it in 5.0. Given how > widely used Bag is, a generous deprecation window seems warranted, > but carrying both forever seems worse than finishing the transition > decided a decade ago. > > [1] https://issues.apache.org/jira/browse/COLLECTIONS-567 > > On Sun, Jul 5, 2026 at 6:53 AM Peter Burka <[email protected]> wrote: > > > > Note that Bag includes the following note which is absent from MultiSet: > > > > > This interface violates the Collection contract. The behavior specified > > in many of these methods is not the same as the behavior specified by > > Collection. The non-compliant methods are clearly marked with > > "(Violation)". Exercise caution when using a bag as a Collection. > > > > The JavaDoc also indicates that Bag was added in 2.0 while MultiSet is > > since 4.1. My guess is that MultiSet is an attempt to fix these violations. > > > > Peter > > > > > > On Sat, Jul 4, 2026 at 2:03 PM Gary Gregory <[email protected]> wrote: > > > > > On Sat, Jul 4, 2026 at 9:36 AM Elliotte Rusty Harold <[email protected]> > > > wrote: > > > > > > > > There's no good reason I can see to have both. Multiset and bag are > > > > different names for the same thing. > > > > > > > > Now if you're asking why this mistake was made in the first place, I > > > > can speculate and the commit history might have some clues. > > > > > > The first commit for both interfaces is from Thomas Neidhart so maybe > > > he can clarify. > > > > > > Gary > > > > > > > > > > > On Thu, Jul 2, 2026 at 9:42 PM Gary Gregory <[email protected]> > > > wrote: > > > > > > > > > > Hi All, > > > > > > > > > > Why do we have both Bag and MultiSet? They seem to do the same thing. > > > > > > > > > > Gary > > > > > > > > > > --------------------------------------------------------------------- > > > > > To unsubscribe, e-mail: [email protected] > > > > > For additional commands, e-mail: [email protected] > > > > > > > > > > > > > > > > > -- > > > > Elliotte Rusty Harold > > > > [email protected] > > > > > > > > --------------------------------------------------------------------- > > > > To unsubscribe, e-mail: [email protected] > > > > For additional commands, e-mail: [email protected] > > > > > > > > > > --------------------------------------------------------------------- > > > To unsubscribe, e-mail: [email protected] > > > For additional commands, e-mail: [email protected] > > > > > > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
