java 和 C# 对“将下划线方式命名的字符串转换为驼峰式”的效率

对下划线方式命名的字符串转换为驼峰式
java:

    static String toCamelCase(String str) {
        String[] ss = str.split("_");
        StringBuilder sb = new StringBuilder();
        for (String s : ss) {
            sb.append(Character.toUpperCase(s.charAt(0)));
            sb.append(s.substring(1));
        }
        return toFirstLower(sb.toString());
    }


    static String toFirstLower(String str) {
        if (StrUtil.isNotEmpty(str))
            return Character.toLowerCase(str.charAt(0)) + str.substring(1);
        return str;
    }

还有 HuTool 中的

public static String toCamelCase(CharSequence name) {
        if (null == name) {
            return null;
        }

        final String name2 = name.toString();
        if (contains(name2, CharUtil.UNDERLINE)) {
            final int length = name2.length();
            final StringBuilder sb = new StringBuilder(length);
            boolean upperCase = false;
            for (int i = 0; i < length; i++) {
                char c = name2.charAt(i);

                if (c == CharUtil.UNDERLINE) {
                    upperCase = true;
                } else if (upperCase) {
                    sb.append(Character.toUpperCase(c));
                    upperCase = false;
                } else {
                    sb.append(Character.toLowerCase(c));
                }
            }
            return sb.toString();
        } else {
            return name2;
        }
    }

测试代码

            // 创建一个计时器
            StopWatch watch = new StopWatch();
            String name = "sys_res_dict_cate_a3333";
            // 计时器开始
            watch.start();
            for (int i = 0; i < 1000000; i++) {
                StrUtil.toCamelCase(name);
            }
            watch.stop();
            System.out.println(watch.getTotalTimeMillis());
            watch = new StopWatch();
            watch.start();

            for (int i = 0; i < 1000000; i++) {
                toCamelCase(name);
            }
            watch.stop();
            System.out.println(watch.getTotalTimeMillis());

运行结果为:
544
1409

而用C#

        /// <summary>
        /// 驼峰状 + 大写首字符
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToUpcaseNameOld(this string name)
        {
            var builder = new StringBuilder();
            foreach (var s in name.Split(new[] { '_', '.' }, StringSplitOptions.RemoveEmptyEntries))
            {
                builder.Append(char.ToUpper(s[0]));
                builder.Append(s[1..]);
            }

            return builder.ToString();
        }

        public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
            foreach (var item in collection)
            {
                action(item);
            }
        }


        /// <summary>
        /// 驼峰状
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToUpcaseCamelName(this string name)
        {
            return GetName(name, false);
        }


        /// <summary>
        /// 驼峰状 + 大写首字符
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string ToUpcaseName(this string name)
        {
            return GetName(name, true);
        }

        private static string GetName(string name, bool b)
        {
            StringBuilder builder = new StringBuilder();
            name.ForEach(i =>
            {
                if (i == '_')
                {
                    b = true;
                }
                else if (b)
                {
                    builder.Append(char.ToUpper(i));
                    b = false;
                }
                else
                {
                    builder.Append(char.ToLower(i));
                }
            });

            return builder.ToString();
        }

测试代码:

            var stopwatch = new Stopwatch();

            var name = "sys_res_dict_cate_a3333";
            stopwatch.Start();
            for (int i = 0; i < 1000000; i++)
            {
                name.ToUpcaseName();
            }
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
            stopwatch.Restart();
            for (int i = 0; i < 1000000; i++)
            {
                name.ToUpcaseNameOld();
            }

            Console.WriteLine(stopwatch.ElapsedMilliseconds);

测试结果:
768
385

总结:

循环字符split
java5441409
C#768385

探究一下,为什么思路一样,java用Split方式比C#的用时多这么多?
CLR 学的少,问一下为什么会出现上述情况。

阅读 3.2k
1 个回答
  1. 这种比较意义不大,牵扯到的东西过于多又过于底层,和大部分人的日常开发扯不上关系
  2. 性能测试要用专门的工具和库(gc,虚拟机预热之类的东西会对测试有很大影响,需要屏蔽)

不懂C#,只说说java这边的问题

  1. hutool的写法很好,可以考虑去掉 contains 判断用空间换时间
  2. 第一种写法很差,会创建很多一次性的 String 对象,正确的写法一定是一个 StringBuilder 从头 append 到尾,不创建任何多余的 String 对象,还应该考虑加入初始化 StringBuilder 长度,避免扩容
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题