替换哈希集Java成员
我有一套这样的结构。我没有副本,但当我调用时:替换哈希集Java成员,java,replace,set,duplicates,Java,Replace,Set,Duplicates,我有一套这样的结构。我没有副本,但当我调用时: set.add(element)->并且已经有了我想要替换的元素 import java.io.*; public class WordInfo implements Serializable { File plik; Integer wystapienia; public WordInfo(File plik, Integer wystapienia) { this.plik = plik;
set.add(element)
->并且已经有了我想要替换的元素
import java.io.*;
public class WordInfo implements Serializable {
File plik;
Integer wystapienia;
public WordInfo(File plik, Integer wystapienia) {
this.plik = plik;
this.wystapienia = wystapienia;
}
public String toString() {
// if (plik.getAbsolutePath().contains("src") && wystapienia != 0)
return plik.getAbsolutePath() + "\tWYSTAPIEN " + wystapienia;
// return "";
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(!(obj instanceof WordInfo)) return false;
return this.plik.equals(((WordInfo) obj).plik);
}
@Override
public int hashCode() {
return this.plik.hashCode();
}
}
检查JDK中的
HashSet
代码。
当添加一个重复的元素时,旧值将被替换。
人们认为新元素被丢弃了,这是错误的。
因此,在您的案例中不需要额外的代码
更新------------------
我重新阅读了JDK中的代码,并承认我犯了一个错误
当执行put
时,值将被替换,而不是HashMap
中的键
为什么我说的是Hashmap??!!因为如果查看哈希集
代码,您会注意到:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
因此,PRESENT
值将替换为新值,如代码的这一部分所示:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
public V put(K键,V值){
if(key==null)
返回putForNullKey(值);
int hash=散列(键);
int i=indexFor(散列,table.length);
for(条目e=表[i];e!=null;e=e.next){
对象k;
如果(e.hash==hash&((k=e.key)==key | | key.equals(k))){
V oldValue=e.value;
e、 价值=价值;
e、 记录存取(本);
返回旧值;
}
}
modCount++;
加法器(散列、键、值、i);
返回null;
}
但是我同意,键
没有被替换,而且由于键
s代表散列集的
值,所以这一个被称为“未触及”。尝试如下操作(只有当等于
和散列码
依赖于一个字段时,这才有意义,但其他字段可能有不同的值):
查看该方法的文档
如果此集合已经包含元素,则调用将保持集合不变并返回false
在每次添加之前执行删除操作:
someSet.remove(myObject);
someSet.add(myObject);
移除将移除与myObject相等的任何对象。或者,您可以检查添加结果:
if(!someSet.add(myObject)) {
someSet.remove(myObject);
someSet.add(myObject);
}
哪个更有效取决于碰撞的频率。如果它们很少见,第二种形式通常只执行一个操作,但当发生碰撞时,它会执行三个操作。第一个表单总是执行两个操作。如果集合中已包含一个元素,该元素
等于您尝试添加的元素()
,则不会添加新元素,也不会替换现有元素。要确保添加新元素,只需先将其从集合中移除:
set.remove(aWordInfo);
set.add(aWordInfo);
我正在处理一个问题,我有一个集合,然后我想用另一个集合中的对象替换/覆盖一些对象 在我的例子中,我最终要做的是创建一个新的集合,并首先放入覆盖,然后再添加当前对象。这是因为在添加新对象时,集合不会替换任何现有对象 如果您有:
Set<WordInfo> currentInfo;
Set<WorldInfo> overrides;
我做到了:
Set<WordInfo> updated = new HashSet<>();
updated.addAll(overrides);
updated.addAll(currentInfo);
Set updated=new HashSet();
更新的.addAll(覆盖);
更新的.addAll(当前信息);
无法理解代码片段与问题之间的关系。你能解释一下,在你的代码中设置它的位置吗?另外,如果您的对象完全相同,那么为什么要替换?@YogendraSingh-OP希望能够将集合中的旧WordInfo
替换为一个新的equals()
旧对象,但不是同一个对象。(请注意,equals()
测试忽略了wystapienia
的值)@TedHopp:Thank,但是仍然返回这个.plik.equals(((WordInfo)obj.plik)
将返回true
,no???@YogendraSingh-我的观点是两个WordInfo
对象可以是equals()
,而不是=
。当两个是相等()
但不是=
时,OP希望能够在集合中用另一个替换一个。OP的问题是:如何进行替换。@TedHopp:我试图通过OP来理解问题本身,即为什么?
,我仍然不相信这一点(可能这是伪示例)。我看到了你对如何的回答,这很好。我现在就离开。感谢您的输入。这是一个不应该依赖的内部实现细节。如果发生替换,则HashSet没有遵循add的Set约定:“调用保持集合不变并返回false”-1这完全是错误的:相同的hashcode并不意味着相同的对象。新元素被丢弃了!请参阅:如果此集合已经包含元素,则调用将保持集合不变并返回false
@Bohemian我从来没有说过我在谈论相同的哈希代码。谈论相同的对象。我已经运行了一个测试,我很高兴确认HashSet确实符合集合契约,保留旧对象以防试图添加与集合中现有元素相等的对象。-1这不起作用。你总是想添加,不管是什么set()
returnsok no-1,但是现在你的答案和Patricia的一样,她是第一个回答“正确”的人,就像一分钟前那样:)工作这导致线程“main”中出现异常java.util.ConcurrentModificationException
当与迭代器
@威胁一起使用时,这是一个与此问题不同的问题,此问题是关于在可以调用add
的情况下更改其行为。我建议把它作为一个新问题来问,背景要比你在评论中能说的更多,除非你能找到对你有帮助的现有问题。嗯,那么我们可以使用简单的List
而不是Set
第二块代码中的if语句可以简化为if(someSet.remove(myObject))如果集合中存在myObject
,则remove
方法也会返回true。我还认为conta
for each override, replace the object in current info
Set<WordInfo> updated = new HashSet<>();
updated.addAll(overrides);
updated.addAll(currentInfo);