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]

Reply via email to