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

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e507fcc  [Enhancement] Improve list comparing performance (#4880)
e507fcc is described below

commit e507fcc3b3ba9c7ed53f74c1b2ef27eee12df005
Author: xinghuayu007 <[email protected]>
AuthorDate: Sun Nov 22 20:35:12 2020 +0800

    [Enhancement] Improve list comparing performance (#4880)
    
    The function equalSets is not efficient enough currently, the time 
complexity is O(n^2).
    To improve the performance of comparing two lists, this patch tries to use 
hash map structure
    to make the time complexity to be O(n).
---
 .../main/java/org/apache/doris/analysis/Expr.java  | 32 ++++++++++++++++++++--
 .../java/org/apache/doris/analysis/ExprTest.java   | 25 +++++++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
index 7f476be..263c30d 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
@@ -50,6 +50,7 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.HashMap;
 
 /**
  * Root of the expr node hierarchy.
@@ -482,13 +483,40 @@ abstract public class Expr extends TreeNode<Expr> 
implements ParseNode, Cloneabl
 
     /**
      * Return true if l1 equals l2 when both lists are interpreted as sets.
-     * TODO: come up with something better than O(n^2)?
      */
     public static <C extends Expr> boolean equalSets(List<C> l1, List<C> l2) {
         if (l1.size() != l2.size()) {
             return false;
         }
-        return l1.containsAll(l2) && l2.containsAll(l1);
+        Map cMap1 = toCountMap(l1);
+        Map cMap2 = toCountMap(l2);
+        if (cMap1.size() != cMap2.size()) {
+            return false;
+        }
+        Iterator it = cMap1.keySet().iterator();
+        while (it.hasNext()) {
+            C obj = (C) it.next();
+            Integer count1 = (Integer) cMap1.get(obj);
+            Integer count2 = (Integer) cMap2.get(obj);
+            if (count2 == null || count1 != count2) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static <C extends Expr> HashMap<C, Integer> toCountMap(List<C> 
list) {
+        HashMap countMap = new HashMap<C,Integer>();
+        for (int i = 0; i < list.size(); i++) {
+            C obj = list.get(i);
+            Integer count = (Integer) countMap.get(obj);
+            if (count == null) {
+                countMap.put(obj, 1);
+            } else {
+                countMap.put(obj, count+1);
+            }
+        }
+        return countMap;
     }
 
     public void analyzeNoThrow(Analyzer analyzer) {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java
index 0b877bb..360a5cf 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprTest.java
@@ -29,6 +29,8 @@ import org.junit.Test;
 
 import java.util.Map;
 import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
 
 import mockit.Expectations;
 import mockit.Injectable;
@@ -159,4 +161,27 @@ public class ExprTest {
         StringLiteral castStringLiteral2 = (StringLiteral) 
stringLiteral.uncheckedCastTo(Type.VARCHAR);
         Assert.assertTrue(stringLiteral == castStringLiteral2);
     }
+
+    @Test
+    public void testEqualSets() {
+        Expr r1 = new DateLiteral(2020, 10, 20);
+        Expr r2 = new DateLiteral(2020, 10, 21);
+        Expr r3 = new DateLiteral(2020, 10, 22);
+        Expr r4 = new DateLiteral(2020, 10, 23);
+
+        //list1 equal list2
+        List<Expr> list1 = new ArrayList<>();
+        List<Expr> list2 = new ArrayList<>();
+        list1.add(r1);
+        list1.add(r2);
+        list1.add(r3);
+        list2.add(r1);
+        list2.add(r2);
+        list2.add(r3);
+        Assert.assertTrue(Expr.equalSets(list1, list2));
+
+        //list3 not equal list4
+        list2.add(r4);
+        Assert.assertFalse(Expr.equalSets(list1, list2));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to