删除重复的字符串实例

本文关键字:字符串 实例 删除 | 更新日期: 2023-09-27 18:31:11

我有近 1,000,000 条记录的数组,每条记录都有一个字段"文件名"。

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

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

.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 冻结几秒钟。

删除重复的字符串实例

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

  1. 在添加字符串时获取字符串的哈希值。
  2. 如果哈希不存在,请将其与字符串关联。
  3. 如果哈希确实存在,请逐个字符比较具有相同哈希的字符串。
  4. 如果比较匹配,请存储对原始字符串的引用,而不是新副本。

假设您有很多重复项,这将减少您的内存占用,但实习可能会表现得更好,因为它是在堆上的较低级别完成的。

您可以将所有字符串粘贴到前缀树中。根据路径名的不同程度,这应该会自动删除公共子字符串。在这个 C# 实现中,在 google 上快速搜索产生了结果。

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

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

GC.Collect();