You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2021/07/24 19:04:31 UTC

[lucenenet] 02/03: Lucene.Net.Support.CollectionExtensions: Made more efficient RemoveAll() method and added RetainAll() for use in rare circumstances when we want to do set actions on ICollection

This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit 0d9abf64c4eb8d3867254bc7f60c4ef1367b3b90
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Fri Jul 23 13:06:43 2021 +0700

    Lucene.Net.Support.CollectionExtensions: Made more efficient RemoveAll() method and added RetainAll() for use in rare circumstances when we want to do set actions on ICollection<T>
---
 src/Lucene.Net/Support/CollectionExtensions.cs | 84 +++++++++++++++++++++++---
 1 file changed, 76 insertions(+), 8 deletions(-)

diff --git a/src/Lucene.Net/Support/CollectionExtensions.cs b/src/Lucene.Net/Support/CollectionExtensions.cs
index 6eb7ed0..12c9f70 100644
--- a/src/Lucene.Net/Support/CollectionExtensions.cs
+++ b/src/Lucene.Net/Support/CollectionExtensions.cs
@@ -1,7 +1,8 @@
-using System;
+using J2N.Collections.Generic.Extensions;
+using System;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
+using JCG = J2N.Collections.Generic;
 
 namespace Lucene.Net.Support
 {
@@ -29,23 +30,90 @@ namespace Lucene.Net.Support
     {
         /// <summary>
         /// Removes the given collection of elements from the source <see cref="ICollection{T}"/>.
+        /// <para/>
+        /// Usage Note: This is the same operation as <see cref="ISet{T}.ExceptWith(IEnumerable{T})"/> or
+        /// <see cref="List{T}.RemoveAll(Predicate{T})"/> with a predicate of <c>(value) => collection.Contains(value)</c>. It is
+        /// recommended to use these alternatives when possible.
         /// </summary>
         /// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
         /// <param name="source">An <see cref="ICollection{T}"/> to remove elements from.</param>
-        /// <param name="removeList">An <see cref="IEnumerable{T}"/> containing the items to remove from <paramref name="source"/>.</param>
+        /// <param name="collection">An <see cref="ICollection{T}"/> containing the items to remove from <paramref name="source"/>.</param>
+        /// <returns><c>true</c> if the collection changed as a result of the call; otherwise, <c>false</c>.</returns>
         [DebuggerStepThrough]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void RemoveAll<T>(this ICollection<T> source, IEnumerable<T> removeList)
+        public static bool RemoveAll<T>(this ICollection<T> source, ICollection<T> collection)
         {
             if (source == null)
                 throw new ArgumentNullException(nameof(source));
+            if (collection == null)
+                throw new ArgumentNullException(nameof(collection));
 
-            if (source.Count == 0) return;
+            if (source.Count == 0) return false;
 
-            foreach (var elt in removeList)
+            if (source is ISet<T> set)
             {
-                source.Remove(elt);
+                int originalCount = set.Count;
+                set.ExceptWith(collection);
+                return originalCount != set.Count;
             }
+            else if (source is IList<T> list)
+            {
+                int removed = list.RemoveAll((value) => collection.Contains(value));
+                return removed > 0;
+            }
+
+            // Slow path for unknown collection types
+            bool modified = false;
+            foreach (var e in collection)
+            {
+                modified |= source.Remove(e);
+            }
+            return modified;
+        }
+
+        /// <summary>
+        /// Retains only the elements in this list that are contained in the specified collection (optional operation).
+        /// In other words, removes from this list all of its elements that are not contained in the specified collection.
+        /// <para/>
+        /// Usage Note: This is the same operation as <see cref="ISet{T}.IntersectWith(IEnumerable{T})"/> or
+        /// <see cref="List{T}.RemoveAll(Predicate{T})"/> with a predicate of <c>(value) => !collection.Contains(value)</c>. It is
+        /// recommended to use these alternatives when possible.
+        /// </summary>
+        /// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
+        /// <param name="source">An <see cref="ICollection{T}"/> to remove elements from.</param>
+        /// <param name="collection">An <see cref="ICollection{T}"/> containing the items to remove from <paramref name="source"/>.</param>
+        /// <returns><c>true</c> if the collection changed as a result of the call; otherwise, <c>false</c>.</returns>
+        [DebuggerStepThrough]
+        public static bool RetainAll<T>(this ICollection<T> source, ICollection<T> collection)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (collection == null)
+                throw new ArgumentNullException(nameof(collection));
+
+            if (source.Count == 0) return false;
+
+            if (source is ISet<T> set)
+            {
+                int originalCount = set.Count;
+                set.IntersectWith(collection);
+                return originalCount != set.Count;
+            }
+            else if (source is IList<T> list)
+            {
+                int removed = list.RemoveAll((value) => !collection.Contains(value));
+                return removed > 0;
+            }
+
+            // Slow path for unknown collection types
+            var toRemove = new JCG.HashSet<T>();
+            foreach (var e in source)
+            {
+                if (!collection.Contains(e))
+                    toRemove.Add(e);
+            }
+            if (toRemove.Count > 0)
+                return source.RemoveAll(toRemove);
+            return false;
         }
     }
 }