删除重复的字符串实例
本文关键字:字符串 实例 删除 | 更新日期: 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完成)。
- 在添加字符串时获取字符串的哈希值。
- 如果哈希不存在,请将其与字符串关联。
- 如果哈希确实存在,请逐个字符比较具有相同哈希的字符串。
- 如果比较匹配,请存储对原始字符串的引用,而不是新副本。
假设您有很多重复项,这将减少您的内存占用,但实习可能会表现得更好,因为它是在堆上的较低级别完成的。
您可以将所有字符串粘贴到前缀树中。根据路径名的不同程度,这应该会自动删除公共子字符串。在这个 C# 实现中,在 google 上快速搜索产生了结果。
我建议您仔细检查您的内存占用是否尚未优化。 .NET 会自动在堆上实习重复字符串,这意味着你可以让多个相同的String
对象指向同一内存地址。只需致电String.Intern(targetString)
.这就是为什么String
是不可变的,StringBuilder
存在。
更直接的是,如果您在处理堆上的剩余字符串时遇到问题,您可以在完成后立即启动垃圾回收(甚至在运行期间定期):
GC.Collect();