浏览代码

improve StringUtil::stripchars performance

Jason Rivard 4 年之前
父节点
当前提交
01850d10a0
共有 1 个文件被更改,包括 97 次插入7 次删除
  1. 97 7
      server/src/main/java/password/pwm/util/java/StringUtil.java

+ 97 - 7
server/src/main/java/password/pwm/util/java/StringUtil.java

@@ -45,7 +45,9 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -572,22 +574,110 @@ public abstract class StringUtil
         return stripAllChars( input, Character::isWhitespace );
     }
 
-    public static String stripAllChars( final String input, final Predicate<Character> stripPredicate )
+    public static String stripAllChars( final String input, final Predicate<Character> characterPredicate )
     {
+        if ( isEmpty( input ) )
+        {
+            return "";
+        }
+
+        if ( characterPredicate == null )
+        {
+            return input;
+        }
+
+        // count of valid output chars
+        int copiedChars = 0;
+
+        // loop through input chars and stop if stripped char is found
+        while ( copiedChars < input.length() )
+        {
+            if ( !characterPredicate.test( input.charAt( copiedChars ) ) )
+            {
+                copiedChars++;
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        // return input string if we made it through input without detecting stripped char
+        if ( copiedChars >= input.length() )
+        {
+            return input;
+        }
+
+        // creating sb with input gives good length value and handles copy of chars so far...
         final StringBuilder sb = new StringBuilder( input );
-        int index = 0;
-        while ( index < sb.length() )
+
+        // loop through remaining chars and copy one by one
+        for ( int loopIndex = copiedChars; loopIndex < input.length(); loopIndex++ )
+        {
+            final char loopChar = input.charAt( loopIndex );
+            if ( !characterPredicate.test( loopChar ) )
+            {
+                sb.setCharAt( copiedChars, loopChar );
+                copiedChars++;
+            }
+        }
+
+        return sb.substring( 0, copiedChars );
+    }
+
+    public static String replaceAllChars( final String input, final Function<Character, Optional<String>> replacementFunction )
+    {
+        if ( isEmpty( input ) )
+        {
+            return "";
+        }
+
+        if ( replacementFunction == null )
         {
-            final char loopChar = sb.charAt( index );
-            if ( stripPredicate.test( loopChar ) )
+            return input;
+        }
+
+        // count of valid output chars
+        int copiedChars = 0;
+
+        // loop through input chars and stop if replacement char is needed
+        while ( copiedChars < input.length() )
+        {
+            final Character indexChar = input.charAt( copiedChars );
+            final Optional<String> replacementStr = replacementFunction.apply( indexChar );
+            if ( replacementStr.isEmpty() )
             {
-                sb.deleteCharAt( index );
+                copiedChars++;
             }
             else
             {
-                index++;
+                break;
             }
         }
+
+        // return input string if we made it through input without detecting replacement char
+        if ( copiedChars >= input.length() )
+        {
+            return input;
+        }
+
+        final StringBuilder sb = new StringBuilder( input.substring( 0, copiedChars ) );
+
+        // loop through remaining chars and copy one by one
+        for ( int loopIndex = copiedChars; loopIndex < input.length(); loopIndex++ )
+        {
+            final char loopChar = input.charAt( loopIndex );
+            final Optional<String> replacementStr = replacementFunction.apply( loopChar );
+            if ( replacementStr.isPresent() )
+            {
+                sb.append( replacementStr.get() );
+            }
+            else
+            {
+                sb.append( loopChar );
+            }
+        }
+
         return sb.toString();
     }