You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Thomas Neidhart (JIRA)" <ji...@apache.org> on 2015/11/27 22:12:14 UTC

[jira] [Closed] (COLLECTIONS-426) performance problem in ListOrderedSet.retainAll()

     [ https://issues.apache.org/jira/browse/COLLECTIONS-426?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Thomas Neidhart closed COLLECTIONS-426.
---------------------------------------

> performance problem in ListOrderedSet.retainAll()
> -------------------------------------------------
>
>                 Key: COLLECTIONS-426
>                 URL: https://issues.apache.org/jira/browse/COLLECTIONS-426
>             Project: Commons Collections
>          Issue Type: Bug
>    Affects Versions: 3.2.1
>         Environment: java 1.6.0_24
> Ubuntu 11.10
>            Reporter: Adrian Nistor
>             Fix For: 4.0-alpha1, 4.0, 4.1
>
>         Attachments: Test.java, patch.diff
>
>
> Hi,
> I am encountering a performance problem in ListOrderedSet.retainAll().
> It appears in version 3.2.1 and also in revision 1365132.  I attached
> a test that exposes this problem and a patch that fixes it.  On my
> machine, for this test, the patch provides a 263X speedup.
> To run the test, just do:
> $ java Test
> The output for the un-patched version is:
> Time is 3682
> The output for the patched version is:
> Time is 14
> The problem is that the code for method
> "ListOrderedSet.retainAll(Collection<?> coll)" is:
> {code:java|borderStyle=solid}
> public boolean retainAll(Collection<?> coll) {
>     boolean result = collection.retainAll(coll);
> ....
> }
> {code}
> because "collection.retainAll(coll)" has quadratic complexity if
> parameter "coll" is a List.  Conceptually, the solution is to call
> "coll.retainAll(collection)" which has linear complexity (not
> quadratic), because "collection" is always a HashSet (we know this,
> because "collection" is an inherited field of ListOrderedSet, and thus
> cannot have another type).  See the
> "java.util.AbstractCollection.retainAll()" code inlined below for why
> one call has quadratic complexity, and the other has linear
> complexity.
> Directly calling "coll.retainAll(collection)" would change the
> behavior of ListOrderedSet.retainAll(), which is why the patch seems a
> bit involved.  In reality, the patch simulates the behavior of
> "coll.retainAll(collection)" (which is just the intersection of two
> collections).  You can easily see this by looking at the patch and at
> the "java.util.AbstractCollection.retainAll()" code inlined below.
> "collection.retainAll(coll)" is "java.util.HashSet.retainAll()", which
> is "java.util.AbstractCollection.retainAll()", which has the code:
> {code:java|borderStyle=solid}
> public boolean retainAll(Collection<?> c) {
>     boolean modified = false;
>     Iterator<E> e = iterator();
>     while (e.hasNext()) {
>         if (!c.contains(e.next())) {
>             e.remove();
>             modified = true;
>         }
>     }
>     return modified;
> }
> {code} 
> Is this a bug, or am I misunderstanding the intended behavior?  If so,
> can you please confirm if the patch is correct?
> Thanks,
> Adrian



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)