You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hudi.apache.org by da...@apache.org on 2026/04/20 02:38:03 UTC

(hudi) branch master updated: chore(common): Consolidate MapUtils into CollectionUtils (#18529)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 91dba3e16dec chore(common): Consolidate MapUtils into CollectionUtils (#18529)
91dba3e16dec is described below

commit 91dba3e16dec11cef8fb5d7e7285916569f38681
Author: voonhous <vo...@gmail.com>
AuthorDate: Mon Apr 20 10:37:57 2026 +0800

    chore(common): Consolidate MapUtils into CollectionUtils (#18529)
    
    - MapUtils.isNullOrEmpty(Map) was byte-identical to CollectionUtils.isNullOrEmpty(Map), and MapUtils.nonEmpty(Map) had no matching overload in CollectionUtils.
    - Move the sole remaining unique helper (containsAll) into CollectionUtils, delete MapUtils, and fold its test into TestCollectionUtils so there is one canonical utility class for Map/Collection emptiness and containment checks.
---
 .../hudi/aws/sync/AWSGlueCatalogSyncClient.java    |  7 +--
 .../action/clean/CleanPlanActionExecutor.java      |  2 +-
 .../apache/hudi/common/util/CollectionUtils.java   |  8 +++
 .../java/org/apache/hudi/common/util/MapUtils.java | 41 -------------
 .../hudi/common/util/TestCollectionUtils.java      | 42 +++++++++++++
 .../org/apache/hudi/common/util/TestMapUtils.java  | 69 ----------------------
 .../org/apache/hudi/hive/HoodieHiveSyncClient.java | 10 ++--
 7 files changed, 59 insertions(+), 120 deletions(-)

diff --git a/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java b/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java
index ccd09675fb51..faf015a9aaf5 100644
--- a/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java
+++ b/hudi-aws/src/main/java/org/apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java
@@ -29,7 +29,6 @@ import org.apache.hudi.common.table.timeline.HoodieTimeline;
 import org.apache.hudi.common.util.CollectionUtils;
 import org.apache.hudi.common.util.CustomizedThreadFactory;
 import org.apache.hudi.common.util.HoodieTimer;
-import org.apache.hudi.common.util.MapUtils;
 import org.apache.hudi.common.util.Option;
 import org.apache.hudi.config.GlueCatalogSyncClientConfig;
 import org.apache.hudi.hadoop.utils.HoodieInputFormatUtils;
@@ -105,8 +104,8 @@ import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 import static org.apache.hudi.common.fs.FSUtils.s3aToS3;
-import static org.apache.hudi.common.util.MapUtils.containsAll;
-import static org.apache.hudi.common.util.MapUtils.isNullOrEmpty;
+import static org.apache.hudi.common.util.CollectionUtils.containsAll;
+import static org.apache.hudi.common.util.CollectionUtils.isNullOrEmpty;
 import static org.apache.hudi.config.GlueCatalogSyncClientConfig.ALL_PARTITIONS_READ_PARALLELISM;
 import static org.apache.hudi.config.GlueCatalogSyncClientConfig.CHANGED_PARTITIONS_READ_PARALLELISM;
 import static org.apache.hudi.config.GlueCatalogSyncClientConfig.GLUE_METADATA_FILE_LISTING;
@@ -1016,7 +1015,7 @@ public class AWSGlueCatalogSyncClient extends HoodieSyncClient {
 
   @Override
   public boolean updateSerdeProperties(String tableName, Map<String, String> serdeProperties, boolean useRealtimeFormat) {
-    if (MapUtils.isNullOrEmpty(serdeProperties)) {
+    if (isNullOrEmpty(serdeProperties)) {
       return false;
     }
 
diff --git a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanActionExecutor.java b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanActionExecutor.java
index 4c57cdd76b59..dbdc9857012d 100644
--- a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanActionExecutor.java
+++ b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/clean/CleanPlanActionExecutor.java
@@ -50,7 +50,7 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 import static org.apache.hudi.common.util.CleanerUtils.SAVEPOINTED_TIMESTAMPS;
-import static org.apache.hudi.common.util.MapUtils.nonEmpty;
+import static org.apache.hudi.common.util.CollectionUtils.nonEmpty;
 
 @Slf4j
 public class CleanPlanActionExecutor<T, I, K, O> extends BaseActionExecutor<T, I, K, O, Option<HoodieCleanerPlan>> {
diff --git a/hudi-common/src/main/java/org/apache/hudi/common/util/CollectionUtils.java b/hudi-common/src/main/java/org/apache/hudi/common/util/CollectionUtils.java
index 6d2c1dfea4dd..c58a3dd9376a 100644
--- a/hudi-common/src/main/java/org/apache/hudi/common/util/CollectionUtils.java
+++ b/hudi-common/src/main/java/org/apache/hudi/common/util/CollectionUtils.java
@@ -69,6 +69,14 @@ public class CollectionUtils {
     return !isNullOrEmpty(c);
   }
 
+  public static boolean nonEmpty(Map<?, ?> m) {
+    return !isNullOrEmpty(m);
+  }
+
+  public static boolean containsAll(Map<?, ?> m1, Map<?, ?> m2) {
+    return m1.entrySet().containsAll(m2.entrySet());
+  }
+
   /**
    * Reduces provided {@link Collection} using provided {@code reducer} applied to
    * every element of the collection like following
diff --git a/hudi-common/src/main/java/org/apache/hudi/common/util/MapUtils.java b/hudi-common/src/main/java/org/apache/hudi/common/util/MapUtils.java
deleted file mode 100644
index 937b4f873fa4..000000000000
--- a/hudi-common/src/main/java/org/apache/hudi/common/util/MapUtils.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.hudi.common.util;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Utils for Java Map.
- */
-public class MapUtils {
-
-  public static boolean isNullOrEmpty(Map<?, ?> m) {
-    return Objects.isNull(m) || m.isEmpty();
-  }
-
-  public static boolean nonEmpty(Map<?, ?> m) {
-    return !isNullOrEmpty(m);
-  }
-
-  public static boolean containsAll(Map<?, ?> m1, Map<?, ?> m2) {
-    return m1.entrySet().containsAll(m2.entrySet());
-  }
-}
diff --git a/hudi-common/src/test/java/org/apache/hudi/common/util/TestCollectionUtils.java b/hudi-common/src/test/java/org/apache/hudi/common/util/TestCollectionUtils.java
index 53ca9b2bebc1..75829f112a38 100644
--- a/hudi-common/src/test/java/org/apache/hudi/common/util/TestCollectionUtils.java
+++ b/hudi-common/src/test/java/org/apache/hudi/common/util/TestCollectionUtils.java
@@ -20,17 +20,59 @@
 package org.apache.hudi.common.util;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
 import static org.apache.hudi.common.util.CollectionUtils.batches;
+import static org.apache.hudi.common.util.CollectionUtils.containsAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 class TestCollectionUtils {
 
+  private static Stream<Arguments> containsAllArgs() {
+    Map<String, String> m0 = new HashMap<>();
+    m0.put("k0", "v0");
+    m0.put("k1", "v1");
+    m0.put("k2", "v2");
+    Map<String, String> m1 = new HashMap<>();
+    m1.put("k1", "v1");
+    Map<String, String> m2 = new HashMap<>();
+    m2.put("k2", "v2");
+    m2.put("k", "v");
+    Map<String, String> m3 = Collections.emptyMap();
+    Map<String, String> m4 = new HashMap<>();
+    m4.put("k0", null);
+    Map<String, Integer> m5 = new HashMap<>();
+    m5.put("k0", 0);
+
+    List<Arguments> argsList = new ArrayList<>();
+
+    argsList.add(Arguments.of(m0, m1, true));
+    argsList.add(Arguments.of(m0, m3, true));
+    argsList.add(Arguments.of(m5, m3, true));
+    argsList.add(Arguments.of(m0, m4, false));
+    argsList.add(Arguments.of(m0, m2, false));
+    argsList.add(Arguments.of(m0, m5, false));
+
+    return argsList.stream();
+  }
+
+  @ParameterizedTest
+  @MethodSource("containsAllArgs")
+  void containsAllOnMaps(Map<?, ?> m1, Map<?, ?> m2, boolean expectedResult) {
+    assertEquals(expectedResult, containsAll(m1, m2));
+  }
+
   @Test
   void getBatchesFromList() {
     assertThrows(IllegalArgumentException.class, () -> {
diff --git a/hudi-common/src/test/java/org/apache/hudi/common/util/TestMapUtils.java b/hudi-common/src/test/java/org/apache/hudi/common/util/TestMapUtils.java
deleted file mode 100644
index 888ded5c49df..000000000000
--- a/hudi-common/src/test/java/org/apache/hudi/common/util/TestMapUtils.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hudi.common.util;
-
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class TestMapUtils {
-
-  private static Stream<Arguments> containsAllArgs() {
-    Map<String, String> m0 = new HashMap<>();
-    m0.put("k0", "v0");
-    m0.put("k1", "v1");
-    m0.put("k2", "v2");
-    Map<String, String> m1 = new HashMap<>();
-    m1.put("k1", "v1");
-    Map<String, String> m2 = new HashMap<>();
-    m2.put("k2", "v2");
-    m2.put("k", "v");
-    Map<String, String> m3 = Collections.emptyMap();
-    Map<String, String> m4 = new HashMap<>();
-    m4.put("k0", null);
-    Map<String, Integer> m5 = new HashMap<>();
-    m5.put("k0", 0);
-
-    List<Arguments> argsList = new ArrayList<>();
-
-    argsList.add(Arguments.of(m0, m1, true));
-    argsList.add(Arguments.of(m0, m3, true));
-    argsList.add(Arguments.of(m5, m3, true));
-    argsList.add(Arguments.of(m0, m4, false));
-    argsList.add(Arguments.of(m0, m2, false));
-    argsList.add(Arguments.of(m0, m5, false));
-
-    return argsList.stream();
-  }
-
-  @ParameterizedTest
-  @MethodSource("containsAllArgs")
-  void containsAll(Map<?, ?> m1, Map<?, ?> m2, boolean expectedResult) {
-    assertEquals(expectedResult, MapUtils.containsAll(m1, m2));
-  }
-}
diff --git a/hudi-sync/hudi-hive-sync/src/main/java/org/apache/hudi/hive/HoodieHiveSyncClient.java b/hudi-sync/hudi-hive-sync/src/main/java/org/apache/hudi/hive/HoodieHiveSyncClient.java
index 892fe9350abe..1bb34bf3d784 100644
--- a/hudi-sync/hudi-hive-sync/src/main/java/org/apache/hudi/hive/HoodieHiveSyncClient.java
+++ b/hudi-sync/hudi-hive-sync/src/main/java/org/apache/hudi/hive/HoodieHiveSyncClient.java
@@ -25,8 +25,8 @@ import org.apache.hudi.common.schema.HoodieSchema;
 import org.apache.hudi.common.table.HoodieTableMetaClient;
 import org.apache.hudi.common.table.timeline.HoodieInstant;
 import org.apache.hudi.common.table.timeline.HoodieTimeline;
+import org.apache.hudi.common.util.CollectionUtils;
 import org.apache.hudi.common.util.ConfigUtils;
-import org.apache.hudi.common.util.MapUtils;
 import org.apache.hudi.common.util.Option;
 import org.apache.hudi.common.util.ReflectionUtils;
 import org.apache.hudi.common.util.StringUtils;
@@ -233,7 +233,7 @@ public class HoodieHiveSyncClient extends HoodieSyncClient {
 
   @Override
   public boolean updateTableProperties(String tableName, Map<String, String> tableProperties) {
-    if (MapUtils.isNullOrEmpty(tableProperties)) {
+    if (CollectionUtils.isNullOrEmpty(tableProperties)) {
       return false;
     }
 
@@ -247,7 +247,7 @@ public class HoodieHiveSyncClient extends HoodieSyncClient {
     try {
       Table table = client.getTable(databaseName, tableName);
       Map<String, String> remoteTableProperties = table.getParameters();
-      if (MapUtils.containsAll(remoteTableProperties, tableProperties)) {
+      if (CollectionUtils.containsAll(remoteTableProperties, tableProperties)) {
         return false;
       }
 
@@ -268,7 +268,7 @@ public class HoodieHiveSyncClient extends HoodieSyncClient {
 
   @Override
   public boolean updateSerdeProperties(String tableName, Map<String, String> serdeProperties, boolean useRealtimeFormat) {
-    if (MapUtils.isNullOrEmpty(serdeProperties)) {
+    if (CollectionUtils.isNullOrEmpty(serdeProperties)) {
       return false;
     }
     if (useJdbcFallback()) {
@@ -289,7 +289,7 @@ public class HoodieHiveSyncClient extends HoodieSyncClient {
       } else {
         serdeInfoName = remoteSerdeInfo.getName();
         Map<String, String> remoteSerdeProperties = remoteSerdeInfo.getParameters();
-        shouldUpdate = !MapUtils.containsAll(remoteSerdeProperties, serdeProperties);
+        shouldUpdate = !CollectionUtils.containsAll(remoteSerdeProperties, serdeProperties);
       }
 
       // check if any change to input/output format