- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
下面显示的代码确实输出:
[b]
[a, b]
但是我希望它在输出中打印两行相同的行。
import java.util.*;
public class Test{
static void test(String... abc) {
Set<String> s = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
s.addAll(Arrays.asList("a", "b"));
s.removeAll(Arrays.asList(abc));
System.out.println(s);
}
public static void main(String[] args) {
test("A");
test("A", "C");
}
}
规范明确指出 removeAll
"Removes all this collection's elements that are also contained in the specified collection."
所以根据我的理解,当前的行为是不可预测的。请帮助我理解这一点
最佳答案
您只阅读了部分文档。您忘记了 TreeSet
中的一个重要段落:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the
Set
interface. (SeeComparable
orComparator
for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but aTreeSet
instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
现在 removeAll
实现来自 AbstractSet
并利用 equals
方法。根据您的代码,您将得到 "a".equals("A")
不是 true
,因此即使您提供了一个管理比较器,元素也不被视为相等它们在 TreeSet
本身中使用时。如果您尝试使用包装器,那么问题就会消失:
import java.util.*;
import java.lang.*;
class Test
{
static class StringWrapper implements Comparable<StringWrapper>
{
public final String string;
public StringWrapper(String string)
{
this.string = string;
}
@Override public boolean equals(Object o)
{
return o instanceof StringWrapper &&
((StringWrapper)o).string.compareToIgnoreCase(string) == 0;
}
@Override public int compareTo(StringWrapper other) {
return string.compareToIgnoreCase(other.string);
}
@Override public String toString() { return string; }
}
static void test(StringWrapper... abc)
{
Set<StringWrapper> s = new TreeSet<>();
s.addAll(Arrays.asList(new StringWrapper("a"), new StringWrapper("b")));
s.removeAll(Arrays.asList(abc));
System.out.println(s);
}
public static void main(String[] args)
{
test(new StringWrapper("A"));
test(new StringWrapper("A"), new StringWrapper("C"));
}
}
这是因为您现在在对象的 equals
和 compareTo
之间提供了一致的实现,因此您永远不会在如何将对象添加到有序集合和集合的所有抽象行为如何使用它们。
这在一般情况下是正确的,Java 代码的一种三规则:如果你实现 compareTo
或 equals
或 hashCode
你应该始终实现所有这些以避免标准集合出现问题(即使 hashCode 不太重要,除非您在任何散列集合中使用这些对象)。这在 Java 文档中多次指定。
关于java - AbstractSet.removeAll() 方法无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43121742/
Set结构图 Set public abstract interface Set extends Collection 不包含重复元素的 collection 重写了eq
是否有记录在案的排除 union 的原因和 intersection来自 abc.Set 的定义方法从而来自 typing.AbstractSet ?结果,我经常不得不使用Union[Set,Froz
好吧,我已经寻找这个问题有一段时间了。我不断收到无法实例化 abstractSet 的错误。它不断要求通用。我添加了通用但仍然没有骰子。 import java.util.AbstractSet; i
下面显示的代码确实输出: [b] [a, b] 但是我希望它在输出中打印两行相同的行。 import java.util.*; public class Test{ static void t
对于 AbstractList,哈希码计算如下: int hashCode = 1; Iterator i = list.iterator(); while (i.hasNext()) {
一边研究抽象类和接口(interface)。我确实想知道为什么 java 集合具有所有抽象类。为什么他们不实现接口(interface)而不是抽象类。我对 AbstractList,AbstractS
我正在尝试用类型注释我的代码,但在涉及集合时我有点困惑。我在 PEP 484 中阅读了一些观点: Note: Dict , List , Set and FrozenSet are mainly us
我是一名优秀的程序员,十分优秀!