关于string的效率,众所周知的恐怕是“+”和StringBuilder了,这些本文就不在赘述了。关于本文,请先回答以下问题(假设都是基于多次循环反复调用的情况下):
1.使用Insert与Format方法,哪个效率更高?
2.Contains(value)与IndexOf(value)谁效率更高?

假如您对此2问不感兴趣或已非常了解,请忽略此文。另外本文将不对文中代码的实际用途做任何解释。

<一> 首先看以下的使用场景

            string str1 = "abc";
string str2 = "";
str1 = string.Format("{0}:{1}", str1, str2);
str1 = str1.Insert(, str2);

接下来开始我们的对比之旅(不包含上述代码),编写如下代码用来向控制台输出结果

        static void WriteTime(string title, long time)
{
Console.WriteLine("{1}用时:{0} ms", time, title);
}

再添加一个方法对字符串进行循环操作

        static long LoopCalc(Action<string, string> action)
{
string[] array = new string[];
for (int i = ; i < array.Length; i++)
{
array[i] = i.ToString();
} Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = ; i < array.Length; i++)
{
action(array[i], "bc");
} sw.Stop();
return sw.ElapsedMilliseconds;
}

添加对string进行Insert与Format的效率对比代码并在Main方法中调用

        static void StringPlusDemo()
{
long inserTime = LoopCalc((x, y) => x.Insert(, y));
long formatTime = LoopCalc((x, y) => string.Format("{0}{1}", y, x));
WriteTime("Insert", inserTime);
WriteTime("Format", formatTime);
}

运行结果如下

明显看到Insert效率更高,但是这种结果有局限性,如果字符串很长,那么经过我亲测他们效率相差无几。

注:我这个只是将Format用于字符串拼接的场景,更高的效率应该仍然是StringBuilder,当然Format的其他不可替代用途太多了,Insert和StringBuilder根本无法替代它,这里就不罗嗦了。

<二> 依然是先看下Contains与IndexOf的使用场景

            string str1 = "abcd";
string str2 = "bc";
if (str1.Contains(str2)) { }
if (str1.IndexOf(str2) > -) { }

在这里仍然使用了上述的LoopCalc方法,并增加如下方法,然后在Main方法中调用其

        static void StringContainsDemo()
{
long indexOfTime = LoopCalc((x, y) => { if (x.IndexOf(y) >= ) { } });
long containersTime = LoopCalc((x, y) => { if (x.Contains(y)) { } });
WriteTime("Contains", containersTime);
WriteTime("IndexOf", indexOfTime);
}

结果

显然Contains效率更高,为什么呢?我之前也不懂为什么,现在来看下String类的源码(关于.NET自带类库的源码可以谷歌搜到官方的下载地址,我忘了地址了),代码很多,我就贴出以下string类中的方法给各位看官

        // Determines the position within this string of the first occurence of the specified
// string, according to the specified search criteria. The search begins at
// the first character of this string, it is case-sensitive and culture-sensitive,
// and the default culture is used.
//
public int IndexOf(String value) {
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this,value);
} // Determines the position within this string of the first occurence of the specified
// string, according to the specified search criteria. The search begins at
// startIndex, it is case-sensitive and culture-sensitve, and the default culture is used.
//
public int IndexOf(String value, int startIndex) {
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this,value,startIndex);
}
        public bool Contains( string value ) {
return ( IndexOf(value, StringComparison.Ordinal) >= );
}

以下是有关Contains调用的IndexOf的重载

        public int IndexOf(String value, StringComparison comparisonType) {
return IndexOf(value, , this.Length, comparisonType);
} public int IndexOf(String value, int startIndex, StringComparison comparisonType) {
return IndexOf(value, startIndex, this.Length - startIndex, comparisonType);
} public int IndexOf(String value, int startIndex, int count, StringComparison comparisonType) {
// Validate inputs
if (value == null)
throw new ArgumentNullException("value"); if (startIndex < || startIndex > this.Length)
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); if (count < || startIndex > this.Length - count)
throw new ArgumentOutOfRangeException("count",Environment.GetResourceString("ArgumentOutOfRange_Count")); switch (comparisonType) {
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); case StringComparison.CurrentCultureIgnoreCase:
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); case StringComparison.InvariantCulture:
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); case StringComparison.InvariantCultureIgnoreCase:
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); case StringComparison.Ordinal:
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.Ordinal); case StringComparison.OrdinalIgnoreCase:
return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); default:
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
}

结论差不多出来了吧,不过这里还牵扯到另一个类CultureInfo.InvariantCulture.CompareInfo,我也看过该类的代码,里头有unsafe代码,不在本文范畴,但是有个结论就是当把我的Demo里的代码的IndexOf改为“x.IndexOf(y, StringComparison.Ordinal)”,那么他们俩的相率将相差无二。

这里没有牵扯到正则匹配以及LastIndexOf,其实正则匹配有时可能效率比上述方式更高,但是要视场景使用,更通用的方式还是建议“IndexOf(value, StringComparison.Ordinal)”或“Contains”方法。

string其本身就是char数组的封装,其或多或少体现着Array的一些特点,那么接下来再来看看在List集合中的关于Contains与IndexOf的情况。

<三> List的IndexOf方法并没有StringComparison枚举作为参数的方法,直接上代码吧

/// <summary>
/// 演示string,在contain中还可延伸List类(实际上string就是char的集合)
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
static long LoopCalcList(Action<List<int>, int> action)
{
List<int>[] array = new List<int>[];
for (int i = ; i < array.Length; i++)
{
array[i] = new List<int>
{
i,,,,,,
};
} Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = ; i < array.Length; i++)
{
action(array[i], );
} sw.Stop();
return sw.ElapsedMilliseconds;
} static void ListContainsDemo()
{
long indexOfTime = LoopCalcList((x, y) => { if (x.IndexOf(y) >= ) { } });
long containersTime = LoopCalcList((x, y) => { if (x.Contains(y)) { } });
WriteTime("Contains", containersTime);
WriteTime("IndexOf", indexOfTime);
}

List中的效率对比

运行结果

很显然在判断是否包含时,我们应该坚定不移的使用Contains。

下面再给出List的源码,各位看官自行分析了,对此不做深入研究

        // Contains returns true if the specified element is in the List.
// It does a linear, O(n) search. Equality is determined by calling
// item.Equals().
//
public bool Contains(T item) {
if ((Object) item == null) {
for(int i=; i<_size; i++)
if ((Object) _items[i] == null)
return true;
return false;
}
else {
EqualityComparer<T> c = EqualityComparer<T>.Default;
for(int i=; i<_size; i++) {
if (c.Equals(_items[i], item)) return true;
}
return false;
}
}

List类的Contains方法

        // Returns the index of the first occurrence of a given value in a range of
// this list. The list is searched forwards from beginning to end.
// The elements of the list are compared to the given value using the
// Object.Equals method.
//
// This method uses the Array.IndexOf method to perform the
// search.
//
public int IndexOf(T item) {
return Array.IndexOf(_items, item, , _size);
} int System.Collections.IList.IndexOf(Object item)
{
if(IsCompatibleObject(item)) {
return IndexOf((T)item);
}
return -;
} // Returns the index of the first occurrence of a given value in a range of
// this list. The list is searched forwards, starting at index
// index and ending at count number of elements. The
// elements of the list are compared to the given value using the
// Object.Equals method.
//
// This method uses the Array.IndexOf method to perform the
// search.
//
public int IndexOf(T item, int index) {
if (index > _size)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
return Array.IndexOf(_items, item, index, _size - index);
} // Returns the index of the first occurrence of a given value in a range of
// this list. The list is searched forwards, starting at index
// index and upto count number of elements. The
// elements of the list are compared to the given value using the
// Object.Equals method.
//
// This method uses the Array.IndexOf method to perform the
// search.
//
public int IndexOf(T item, int index, int count) {
if (index > _size)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); if (count < || index > _size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); return Array.IndexOf(_items, item, index, count);
}

List类的IndexOf方法

总结:

  1.这点效率问题对于某些人来说可能无所谓,但是我觉得更重要的是编码习惯的养成问题。

  2.能用Contains的地方还是尽量使用Contains(发现我改的代码中有不少同事直接用了"IndexOf(value)"),当然会有特殊的例外场景,这里不罗嗦。
  3.关于Insert,我编写了两个扩展方法,如下(方法虽简单,但是给代码带来了更大的优雅性)

        public static string InsertLast(this string source, string str)
{
return source.Insert(source.Length, str);
} public static string InsertFirst(this string source, string str)
{
return source.Insert(, str);
}

 

最后本人不是什么资深狼友,将不会提供任何福利图片作别,抱歉!!

string中Insert与Format效率对比、String与List中Contains与IndexOf的效率对比的更多相关文章

  1. java 中的Number类 Character类 String类 StringBuffer类 StringBuilder类

    1. Number类 Java语言为每一个内置数据类型提供了对应的包装类.所有的包装类(Integer.Long.Byte.Double.Float.Short)都是抽象类Number的子类.这种由编 ...

  2. 手把手实例对比String、StringBuilder字符串的连接效率及StringBuilder和StringBuffer线程安全的比较

    一.字符串连接的效率问题 使用String连接字符串时为什么慢? 小知识点 java中对数组进行初始化后,该数组所占的内存空间.数组长度都是不可变的. 创建一个字符串,为字符串对象分配内存空间,会耗费 ...

  3. Java中的字符串操作(比较String,StringBuiler和StringBuffer)

    一.前言 刚开始学习Java时,作为只会C语言的小白,就为其中的字符串操作而感到震撼.相比之下,C语言在字节数组中保存一个结尾的\0去表示字符串,想实现字符串拼接,还需要调用strcpy库函数或者自己 ...

  4. Java中equals和“==””的区别,String特殊

    public class TestString { /* * java中的数据类型,可分为两类: * 1.基本数据类型,也称为原始数据类型.byte,short,char,int,long,float ...

  5. java 基于JDK中的源码总结下String二

    申明:转载请注明出处,如有商用目的请务必知会本人,感谢. 上一篇文章:http://blog.csdn.net/ts1122/article/details/8738336,介绍了String一些易错 ...

  6. java基础---->String和MessageFormat的format方法

    这里介绍一下String和MessageFormat中的format方法的差异以及实现原理. String与MessageFormat的说明 一.两者的使用场景 String.format:for l ...

  7. C++ string类insert用法总结

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  8. (转)Java中的String为什么是不可变的? -- String源码分析

    背景:被问到很基础的知识点  string  自己答的很模糊 Java中的String为什么是不可变的? -- String源码分析 ps:最好去阅读原文 Java中的String为什么是不可变的 什 ...

  9. format not a string literal and no format arguments

    今天cocos2d-x打包 android的时候报错:format not a string literal and no format arguments 报错点是:__String::create ...

随机推荐

  1. 用scikit-learn和pandas学习线性回归

    对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了. 1. 获取数据,定义问题 没有数据,当然没法研究机器学习 ...

  2. Windws Server 2008 R2 WEB环境配置之MYSQL 5.6.22安装配置

    版本选择 因为MySql的版本越来越多,而作为中小网站者可能没有足够的经济去购买商业版本,所以一般选择免费版,而且功能也是足够使用的. 有钱任性就下载企业版,哈哈. 目前使用最多的版本是mysql i ...

  3. jsonp跨域+ashx(示例)

    前言 做B/S项目的时候,我们一般使用jquery+ashx来实现异步的一些操作,比如后台获取一些数据到前台,但是如果ashx文件不在本项目下,引用的是别的域下的文件,这时候就访问不了.关于jsonp ...

  4. 【记录】ASP.NET MVC 4/5 Authentication 身份验证无效

    在 ASP.NET MVC 4/5 应用程序发布的时候,遇到一个问题,在本应用程序中进行身份验证是可以,但不能和其他"二级域名"共享,在其他应用程序身份验证,不能和本应用程序共享, ...

  5. objective-c 语法快速过(8)

    Block(oc 的数据类型,很常用,本质是c结构体) 类似内联函数,从源代码层看,有函数的结构,而在编译后,却不具备函数的性质.编译时,类似宏替换,使用函数体替换调用处的函数名 Block封装了一段 ...

  6. Dean-Edward的事件系统实现

    jQuery早期的事件系统,主要借鉴自Dean-Edward的事件模型.虽说早期的该事件模型也有些许bug,诸如: 1,绑定的事件及其处理程序等数据并未存储到缓存中,而是直接存储在dom元素上,这样不 ...

  7. 浅谈2D游戏设计模式2- WZ文件详解(UI.WZ)之MapLogin.img(1)

    玩过冒险岛的人都知道有一个WZ文件,那么这个WZ文件的内部是怎么样的呢,今天我就带大家一探究竟. 说实在的,我这是第一次接触WZ文件,但是却让我很震撼,为什么很震撼,因为这个居然是用VS2010写的! ...

  8. Android之圆形头像裁切

    PS:今天项目测试组发现,百度地图定位的数据坐标位置是正确的,但是显示的数据是错误的.最后查来查去发现,那个商厦在百度地图上根本就没有那条数据,这让我如何显示,当初就推崇使用高德地图定位,上面的数据量 ...

  9. BizTalk Server 2016

    10月28日微软正式发布BizTalk第十个版本BizTalk Server 2016,陆续发布了Azure VM镜像.MSDN版本.开发者版本等.以下为BizTalk Server 2016 新特性 ...

  10. 【原创】Kafka topic常见命令解析

    本文着重介绍几个常用的topic命令行命令,包括listTopic,createTopic,deleteTopic和describeTopic等.由于alterTopic并不是很常用,本文中就不涉及了 ...