如何更改Java Set的retainall方法以使用equals方法而不是==运算符?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何更改Java Set的retainall方法以使用equals方法而不是==运算符?相关的知识,希望对你有一定的参考价值。
我试图测试HashSets
的两个Strings
是否包含相同的Strings
。 Java集的retainAll()
方法(据我所知,它实现了Collection接口)是检查两个集合的交集的好方法。但是,此方法似乎使用==
样式检查是否相等,以检查它们是否是对同一内存对象的引用,而不是使用String的equals()
方法来检查内容是否相同。有没有办法得到像retainAll这样的东西,但是使用equals()
方法?
我正在尝试编写代码来检查String是否包含来自某个其他String的特定长度的子字符串。我的策略是创建包含该长度的所有子串的每个String的HashSet,然后检查Sets是否包含共同的字符串。
我目前的解决方案是创建自己的静态方法,执行我想要retainAll方法的操作。
static boolean containsEqualElement(Set SetOne, Set SetTwo) {
Iterator it = SetOne.iterator();
while (it.hasNext()) {
Object thisComp = it.next();
Iterator it2 = SetTwo.iterator();
while (it2.hasNext()) {
if (it2.next().equals(thisComp)) {
return true;
}
}
}
return false;
}
我不确定这个方法的效率如何与retainAll方法相比。
您的问题中的陈述:
但是,这个方法似乎使用==样式检查是否测试它们是否是对同一个内存对象的引用,而不是使用String的equals()方法来检查内容是否相同
是错的。 retainAll
确实使用contains
,后者又使用equals
。
我不完全理解你的用例,但我认为你可能会发现Collections.disjoint
方法比retainAll
更有用。来自文档:
如果两个指定的集合没有共同的元素,则返回
true
。
你可以像这样使用它:
if (!Collections.disjoint(setOne, setTwo)) {
// sets have at least one element in common
}
我建议你使用这个方法,因为retainAll
修改了它被调用的集合。实际上,它会删除此集合中未包含在参数集合中的所有元素。从您的代码中,您似乎不希望这种行为。
实际上保留所有使用包含本身使用等于,至少标准版本。也许你实际上使用的是IdentityHashMap,它确实会使用内存引用来实现相等,但这可能是因为你要求它。
public boolean [More ...] retainAll(Collection<?> c) {
boolean modified = false;
Iterator<E> e = iterator();
while (e.hasNext()) {
if (!c.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
}
public boolean [More ...] contains(Object o) {
Iterator<E> e = iterator();
if (o==null) {
while (e.hasNext())
if (e.next()==null)
return true;
} else
while (e.hasNext()
if (o.equals(e.next()))
return true;
}
return false;
}
下次,请考虑使用调试器进行双重检查(甚至来自JDK的代码)或谷歌它(如HashSet.retainAll代码源)你会发现类似的东西:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashSet.java
这就是我回答你的问题所做的。
如果你检查OpenJDK9 source code,你可以看到retainAll()使用AbstractCollection.contains(Object o):
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
contains()的文档说:
如果此collection包含指定的元素,则返回true。更正式地,当且仅当此集合包含至少一个元素e时才返回true(o == null?e == null:o.equals(e))。
因此retainAll()基于equals()检查,这是你想要的。
以上是关于如何更改Java Set的retainall方法以使用equals方法而不是==运算符?的主要内容,如果未能解决你的问题,请参考以下文章