Java正则表达式提供任何性能优势?

在Java中,当我们尝试使用正则表达式进行模式匹配时。 例如,输入一个字符串并使用正则表达式来确定它是否是数字。 如果不是,则抛出异常。 在这种情况下,我明白,使用正则表达式可以减少代码冗长,比如果我们要获取字符串的每个字符,检查它是否是数字,是否抛出异常。

但我认为正则表达式也使得这个过程更有效率。 这是真的? 在这一点上我找不到任何证据。 正则表达式如何在幕后进行比赛? 它是不是也遍历字符串并逐个检查每个字符?


为了好玩,我已经运行了这个微基准。 最后一次运行的结果(即JVM后期热身/ JIT)低于(无论如何,从一次运行到另一次运行结果都是相当一致的):

regex with numbers 123
chars with numbers 33
parseInt with numbers 33
regex with words 123
chars with words 34
parseInt with words 733

换句话说,字符是非常有效的,Integer.parseInt与char相同,如果字符串是一个数字,但是如果字符串不是数字,则非常慢。 正则表达式介于两者之间。

结论

如果将一个字符串解析为一个数字,并且您希望该字符串通常是一个数字,那么使用Integer.parseInt是最好的解决方案(高效且可读)。 如果字符串不是一个数字,那么得到的惩罚应该是低的,如果它不太频繁。

ps:我的正则表达式可能不是最优的,随时发表评论。

public class TestNumber {

    private final static List<String> numbers = new ArrayList<>();
    private final static List<String> words = new ArrayList<>();

    public static void main(String args[]) {
        long start, end;
        Random random = new Random();

        for (int i = 0; i < 1000000; i++) {
            numbers.add(String.valueOf(i));
            words.add(String.valueOf(i) + "x");
        }

        for (int i = 0; i < 5; i++) {
            start = System.nanoTime();
            regex(numbers);
            System.out.println("regex with numbers " + (System.nanoTime() - start) / 1000000);
            start = System.nanoTime();
            chars(numbers);
            System.out.println("chars with numbers " + (System.nanoTime() - start) / 1000000);
            start = System.nanoTime();
            exception(numbers);
            System.out.println("exceptions with numbers " + (System.nanoTime() - start) / 1000000);

            start = System.nanoTime();
            regex(words);
            System.out.println("regex with words " + (System.nanoTime() - start) / 1000000);
            start = System.nanoTime();
            chars(words);
            System.out.println("chars with words " + (System.nanoTime() - start) / 1000000);
            start = System.nanoTime();
            exception(words);
            System.out.println("exceptions with words " + (System.nanoTime() - start) / 1000000);
        }
    }

    private static int regex(List<String> list) {
        int sum = 0;
        Pattern p = Pattern.compile("[0-9]+");
        for (String s : list) {
            sum += (p.matcher(s).matches() ? 1 : 0);
        }
        return sum;
    }

    private static int chars(List<String> list) {
        int sum = 0;

        for (String s : list) {
            boolean isNumber = true;
            for (char c : s.toCharArray()) {
                if (c < '0' || c > '9') {
                    isNumber = false;
                    break;
                }
            }
            if (isNumber) {
                sum++;
            }
        }
        return sum;
    }

    private static int exception(List<String> list) {
        int sum = 0;

        for (String s : list) {
            try {
                Integer.parseInt(s);
                sum++;
            } catch (NumberFormatException e) {
            }
        }
        return sum;
    }
}

我还没有技术答案,但我可以写一些代码并查看。 我不认为正则表达式是将字符串转换为数字的方式。 在很多情况下,它们可以更高效,但如果写得不好,速度会很慢。

请问,为什么你不使用: Integer.parseInt("124") ? 这将抛出NumberFormatException。 应该能够处理它,并且它将检测到一个数字直到核心Java。


关于幕后的正则表达式...

有限状态机(FSM)相当于一个正则表达式。 FSM是一种可识别语言的机器(在您的案例中)。 FSM有一个字母表,一个状态,一个初始状态,N个终止状态以及从一个状态到另一个状态的转换功能。 该字符串需要包含在字母表中(例如,ASCII)。 FSM从初始状态开始。 当你输入一个字符串时,它会根据一个函数(state,char)=>状态从一个状态移动到另一个状态。 当它达到最终状态时,你知道你的字符串是否是数字。

有关更多信息,请参阅FSM并参阅基于自动机的编程

链接地址: http://www.djcxy.com/p/15255.html

上一篇: Java regular expression offers any performance benefit?

下一篇: regex vs while loops