You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by GitBox <gi...@apache.org> on 2019/06/30 12:01:31 UTC

[GitHub] [maven] gnodet commented on a change in pull request #262: Improve speed in collection merging

gnodet commented on a change in pull request #262: Improve speed in collection merging
URL: https://github.com/apache/maven/pull/262#discussion_r298830893
 
 

 ##########
 File path: maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java
 ##########
 @@ -3018,4 +2618,298 @@ protected Object getExclusionKey( Exclusion exclusion )
         return exclusion;
     }
 
+    interface KeyComputer<T>
+    {
+        Object key( T t );
+    }
+
+    class DependencyKeyComputer implements KeyComputer<Dependency>
+    {
+        @Override
+        public Object key( Dependency dependency )
+        {
+            return getDependencyKey( dependency );
+        }
+    }
+
+    class LicenseKeyComputer implements KeyComputer<License>
+    {
+        @Override
+        public Object key( License license )
+        {
+            return getLicenseKey( license );
+        }
+    }
+
+    class MailingListKeyComputer implements KeyComputer<MailingList>
+    {
+        @Override
+        public Object key( MailingList mailingList )
+        {
+            return getMailingListKey( mailingList );
+        }
+    }
+
+    class DeveloperKeyComputer implements KeyComputer<Developer>
+    {
+        @Override
+        public Object key( Developer developer )
+        {
+            return getDeveloperKey( developer );
+        }
+    }
+
+    class ContributorKeyComputer implements KeyComputer<Contributor>
+    {
+        @Override
+        public Object key( Contributor contributor )
+        {
+            return getContributorKey( contributor );
+        }
+    }
+
+    class ProfileKeyComputer implements KeyComputer<Profile>
+    {
+        @Override
+        public Object key( Profile profile )
+        {
+            return getProfileKey( profile );
+        }
+    }
+
+    class RepositoryKeyComputer implements KeyComputer<Repository>
+    {
+        @Override
+        public Object key( Repository repository )
+        {
+            return getRepositoryKey( repository );
+        }
+    }
+
+    class ReportPluginKeyComputer implements KeyComputer<ReportPlugin>
+    {
+        @Override
+        public Object key( ReportPlugin plugin )
+        {
+            return getReportPluginKey( plugin );
+        }
+    }
+
+    class PluginKeyComputer implements KeyComputer<Plugin>
+    {
+        @Override
+        public Object key( Plugin plugin )
+        {
+            return getPluginKey( plugin );
+        }
+    }
+
+    class ReportSetKeyComputer implements KeyComputer<ReportSet>
+    {
+        @Override
+        public Object key( ReportSet reportSet )
+        {
+            return getReportSetKey( reportSet );
+        }
+    }
+
+    class NotifierKeyComputer implements KeyComputer<Notifier>
+    {
+        @Override
+        public Object key( Notifier notifier )
+        {
+            return getNotifierKey( notifier );
+        }
+    }
+
+    class ExtensionKeyComputer implements KeyComputer<Extension>
+    {
+        @Override
+        public Object key( Extension extension )
+        {
+            return getExtensionKey( extension );
+        }
+    }
+
+    class ResourceKeyComputer implements KeyComputer<Resource>
+    {
+        @Override
+        public Object key( Resource resource )
+        {
+            return getResourceKey( resource );
+        }
+    }
+
+    class ExecutionKeyComputer implements KeyComputer<PluginExecution>
+    {
+        @Override
+        public Object key( PluginExecution pluginExecution )
+        {
+            return getPluginExecutionKey( pluginExecution );
+        }
+    }
+
+    class ExclusionKeyComputer implements KeyComputer<Exclusion>
+    {
+        @Override
+        public Object key( Exclusion exclusion )
+        {
+            return getExclusionKey( exclusion );
+        }
+    }
+
+    static <T> List<T> merge( List<T> tgt, List<T> src, boolean sourceDominant, KeyComputer<T> computer )
+    {
+        if ( src.isEmpty() )
+        {
+            return tgt;
+        }
+
+        MergingList<T> list;
+        if ( tgt instanceof MergingList )
+        {
+            list = (MergingList<T>) tgt;
+        }
+        else
+        {
+            list = new MergingList<>( computer, src.size() + tgt.size() );
+            list.mergeAll( tgt, true );
+        }
+
+        list.mergeAll( src, sourceDominant );
+        return list;
+    }
+
+    /**
+     * Merging list
+     * @param <V>
+     */
+    public static class MergingList<V> extends AbstractList<V>
+    {
+        private final KeyComputer<V> keyComputer;
+        private Map<Object, V> map;
+        private List<V> list;
 
 Review comment:
   @Tibor17 this is an internal object, the keys are the same that were used in Maps previously, so this is similar to the current code.
   Thread safety is not a concern because merging happens in a single thread, and the current code uses an ArrayList to hold objects, which is not thread safe either.
   @eolivelli the point is to avoid switching back and forth between maps and list during the merging time.  
   
   Ideally, the model would be changed so that Plugin, Dependency and other merged objects would implement `equals` and `hashCode` instead of relying on `computeXxxKey`.  And those objects would be stored in a `Set` rather than a `List`.  But I didn't want to break compatibility at all, so I haven't changed the data structures.
   I also did not want to risk breaking compatibility by using a non complete List implementation, so I decided to revert to the List whenever it is actually accessed (which does not happen during project build, but could be in maven plugins later).
   I've chosen to try to keep full compatibility, but if you prefer a more conside code without the duplicate map/list backend, I can refactor, but there will be a risk of breaking compatibility.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services