我有这种情况,其中内存保护是至关重要的。我正在尝试阅读> 1 GB的肽序列共存于共享相同序列的记忆和组肽实例中。我将Peptide对象存储在Hash中,因此我可以快速检查重复,但发现即使知道Set包含该对象,也无法访问Set中的对象。
内存非常重要,如果可能,我不想复制数据。 (否则我会将我的数据结构设计为:peptides = Dictionary<string, Peptide>
,但这会复制字典和Peptide类中的字符串)。下面是代码,向您展示我想要完成的任务:
public SomeClass {
// Main Storage of all the Peptide instances, class provided below
private HashSet<Peptide> peptides = new HashSet<Peptide>();
public void SomeMethod(IEnumerable<string> files) {
foreach(string file in files) {
using(PeptideReader reader = new PeptideReader(file)) {
foreach(DataLine line in reader.ReadNextLine()) {
Peptide testPep = new Peptide(line.Sequence);
if(peptides.Contains(testPep)) {
// ** Problem Is Here **
// I want to get the Peptide object that is in HashSet
// so I can add the DataLine to it, I don't want use the
// testPep object (even though they are considered "equal")
peptides[testPep].Add(line); // I know this doesn't work
testPep.Add(line) // THIS IS NO GOOD, since it won't be saved in the HashSet which i use in other methods.
} else {
// The HashSet doesn't contain this peptide, so we can just add it
testPep.Add(line);
peptides.Add(testPep);
}
}
}
}
}
}
public Peptide : IEquatable<Peptide> {
public string Sequence {get;private set;}
private int hCode = 0;
public PsmList PSMs {get;set;}
public Peptide(string sequence) {
Sequence = sequence.Replace('I', 'L');
hCode = Sequence.GetHashCode();
}
public void Add(DataLine data) {
if(PSMs == null) {
PSMs = new PsmList();
}
PSMs.Add(data);
}
public override int GethashCode() {
return hCode;
}
public bool Equals(Peptide other) {
return Sequence.Equals(other.Sequence);
}
}
public PSMlist : List<DataLine> { // and some other stuff that is not important }
为什么HashSet
不让我获得HashSet中包含的对象引用?我知道人们会试着说如果HashSet.Contains()
返回true,那么你的对象是等价的。它们在值方面可能是等价的,但我需要引用相同,因为我在Peptide类中存储了其他信息。
我提出的唯一解决方案是Dictionary<Peptide, Peptide>
,其中键和值都指向相同的引用。但这似乎很俗气。还有其他数据结构可以实现吗?
答案 0 :(得分:9)
基本上你可以自己重新实现HashSet<T>
,但这是我所知道的唯一解决方案。 Dictionary<Peptide, Peptide>
或Dictionary<string, Peptide>
解决方案可能不会 效率低下 - 如果您每个条目只浪费一个参考,我会认为这相对无关紧要。
实际上,如果从hCode
中删除Peptide
成员,那么每个对象将保护4个字节,这与x86中的引用大小相同......缓存中没有任何意义据我所知,哈希只会计算每个对象的哈希值,至少在您显示的代码中是这样。
如果你真的非常绝望的内存,我怀疑你可以比string
更有效地存储序列。如果您向我们提供有关序列所包含内容的更多信息,我们可能会在那里提出一些建议。
我不知道有任何特别强烈的原因为什么HashSet
不允许这样做,除了这是一个相对罕见的要求 - 但这是我见过的要求在Java中也是......
答案 1 :(得分:1)
使用Dictionary<string, Peptide>
。