重复数据删除字符串实例

时间:2013-09-12 23:35:40

标签: c# .net string .net-2.0 deduplication

我有近1,000,000条记录的数组,每条记录都有一个字段“filename”。

有许多记录具有完全相同的文件名。

我的目标是通过重复数据删除字符串实例(文件名实例,而不是记录)来改善内存占用。

.NET Framework 2.0是一种约束。这里没有LINQ。

我为重复数据删除写了一个通用(和线程安全)类:

public class Deduplication<T>
    where T : class
{
    private static Deduplication<T> _global = new Deduplication<T>();

    public static Deduplication<T> Global
    {
        get { return _global; }
    }

    private Dictionary<T, T> _dic;// = new Dictionary<T, T>();
    private object _dicLocker = new object();

    public T GetInstance(T instance)
    {
        lock (_dicLocker)
        {
            if (_dic == null)
            {
                _dic = new Dictionary<T, T>();
            }

            T savedInstance;
            if (_dic.TryGetValue(instance, out savedInstance))
            {
                return savedInstance;
            }
            else
            {
                _dic.Add(instance, instance);
                return instance;
            }
        }
    }

    public void Clear()
    {
        lock (_dicLocker)
        {
            _dic = null;
        }
    }
}

这个类的问题在于它增加了更多的内存使用量,它会一直保留到下一个GC。

我正在寻找一种减少内存占用的方法,而无需增加更多的内存使用量,也无需等待下一代GC。此外,我不想使用GC.Collect(),因为它会冻结GUI几秒钟。

3 个答案:

答案 0 :(得分:1)

如果你不想实习你的琴弦。您可以采用类似的方法来处理Java 8的字符串重复数据删除(由堆上的GC完成)。

  1. 在添加字符串时获取字符串的哈希值。
  2. 如果哈希不存在,请将其与字符串相关联。
  3. 如果哈希确实存在,请按字符比较具有相同哈希字符的字符串。
  4. 如果您的比较匹配,请存储对原始字符串的引用,而不是新副本。
  5. 如果您有很多重复项,这会减少您的内存占用,但是实际上可能会执行得更好,因为它是在堆上的较低级别完成的。

答案 1 :(得分:0)

您可以将所有字符串粘贴在前缀树中。根据您的路径名称的不同,这应该自动重复删除常见的子串。谷歌的快速搜索产生于this C# implementation

答案 2 :(得分:-1)

我建议您仔细检查您的内存占用情况是否已经过优化。 .NET会自动在堆上实现重复的字符串,这意味着您可以将多个相同的String对象指向相同的内存地址。只需致电String.Intern(targetString)即可。这就是为什么String是不可变的,StringBuilder存在。

更快的是,如果您在堆上的剩余字符串遇到问题,您可以在完成后立即启动垃圾收集(甚至在运行期间定期启动):

GC.Collect();