为什么字符串出了名的昂贵

时间:2009-07-17 16:21:28

标签: c# string

实现字符串的方式是什么让它们操作起来如此昂贵?

是否无法实现“廉价”的字符串实现?

或者我的理解完全错了?

由于

9 个答案:

答案 0 :(得分:22)

使用哪种语言?

字符串通常是不可变的,这意味着对数据的任何更改都会导致正在创建的字符串的新副本。这可能会对大字符串产生性能影响。

然而,这是一项重要功能,因为它允许进行优化,例如实习。 Interning通过将相同的字符串指向同一个数据副本来减小文本数据的大小。

如果您担心字符串的性能,请使用StringBuilder(可在C#和Java中使用)或其他使用可变文本数据的构造。

如果您正在处理大量文本数据并需要强大的字符串解决方案,同时仍可节省空间,look into using ropes

答案 1 :(得分:2)

字符串的问题在于它们不是原始类型。它们是数组。 因此,它们遇到与数组相同的速度和内存问题(可能还有一些优化)。

现在,“廉价”的实现需要很多东西:连接,indexOf等。 有很多方法可以做到这一点。您可以改进实施,但有一些限制。因为字符串对于计算机来说不是“自然的”,它们需要更多的内存并且操作起来更慢......总是如此。你永远不会比任何体面的整数和算法更快地获得字符串连接算法。

答案 2 :(得分:2)

由于它每次在java中创建对象的新副本,因此建议使用StringBuffer

语法

StringBuffer strBuff=new StringBuffer();
strBuff.append("StringBuffer");
strBuff.append("is");
strBuff.append("more");
strBuff.append("economical");
strBuff.append("than");
strBuff.append("String");
String string=strBuff.tostring();

答案 3 :(得分:2)

这里的许多要点都很好。在单独的情况下,您可能会作弊并做一些事情,例如使用64位int来比较字符串中的8个字节,但是没有很多可以优化操作的通用情况。如果你有“pascal样式”字符串与数字长度字段比较可以短路逻辑只检查字符串的其余部分,如果长度不一样。其他操作通常要求您一次处理字符或在使用时完全复制它们。 即连接=>获取字符串1的长度,获取字符串2的长度,分配的内存,复制字符串1,复制字符串2.可以使用字符串库中的DMA控制器执行此类操作,但是将其设置为小的开销字符串会超过好处。

皮特

答案 4 :(得分:1)

这完全取决于你尝试用它做什么。主要是它通常需要至少1个新的数组分配,除非它在直接搜索中替换单个字符。在最简单的级别,字符串是一个字符数组。因此,您想要做的任何事情都涉及迭代,删除或将新事物插入到数组中。

答案 5 :(得分:1)

查看可变字符串,不可变字符串和ropes,并考虑如何使用低级语言(例如,C)实现常见操作。考虑:

  1. 级联。
  2. 切片。
  3. 在索引处获取角色。
  4. 更改索引处的字符。
  5. 找到角色的索引。
  6. 遍历字符串。
  7. 为这些情况提供算法可以让您了解每种类型的存储何时适合。

答案 6 :(得分:0)

如果你想在各种条件下使用通用字符串,在某些情况下你必须牺牲效率。这是在快速获得一件事与另一件事之间的经典权衡。所以...要么使用“标准”字符串正常工作(但不能以最佳方式工作),要么使用字符串实现,在某些情况下速度非常快,而在其他情况下则很麻烦。

有时你需要不变性,有时是随机访问,有时是快速插入/删除......

答案 7 :(得分:0)

字符串的更改和复制往往涉及内存管理。

内存管理对性能不利,因为它往往需要某种全局互斥体,这会使您的代码在多个内核中的扩展性很差。

答案 8 :(得分:0)

你想阅读这篇Joel Spolsky的文章:

http://www.joelonsoftware.com/articles/fog0000000319.html

我,我很失望.NET没有名为F***edString的原生类型。