当前位置: 首页 > 面试题库 >

TreeSet提供错误的输出-Java8

钱哲茂
2023-03-14
问题内容

在使用树集时,我发现了非常奇怪的行为。

根据我的理解,以下程序应打印两条相同的行:

public class TestSet {
    static void test(String... args) {
        Set<String> s = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
        s.addAll(Arrays.asList("a", "b"));
        s.removeAll(Arrays.asList(args));
        System.out.println(s);
    }

    public static void main(String[] args) {
        test("A");
        test("A", "C");
    }
}

但奇怪的是它打印:

[b]
[a, b]

我无法理解-为什么树集的行为如此?


问题答案:

发生这种情况是因为SortedSet的Comparator用于排序,但是removeAll依赖于equals每个元素的方法。从SortedSet文档中:

请注意,如果排序集要正确实现接口,则排序集(无论是否提供显式比较器)所维护的顺序必须
与equals一致Set。(请参见Comparable接口或Comparator接口,以获得 与equals一致 的精确定义
)之所以如此,是因为Set接口是根据equals操作定义的,但是排序后的集合使用其compareTo(或compare方法执行所有元素比较,因此两个元素从排序集的角度来看,此方法认为相等是相等的。即使排序顺序与equals不一致,也
可以 很好地定义排序集的行为。它只是不遵守总合同Set 接口。


可比文档中定义了“等于”的解释:

一类的自然顺序C被说成是 与equals一致 当且仅当e1.compareTo(e2) == 0具有相同的布尔值的e1.equals(e2)每一个e1e2阶级的C。请注意,null不是任何类的实例,并e.compareTo(null)应抛出NullPointerException,即使e.equals(null)回报false

强烈建议(尽管不是必需的)自然顺序应与等号保持一致。之所以如此,是因为没有显式比较器的排序集(和排序映射)在与自然排序与等式不一致的元素(或键)一起使用时,表现为“奇怪”。特别是,这样的排序集(或排序图)违反了根据equals方法定义的集合(或图)的一般约定。

总之,集合的比较器的行为与元素的equals方法不同,从而导致异常(尽管可预测)行为。



 类似资料:
  • 因此,在迁移到其他主机,导出和导入数据库,修复链接后,我得到了一些奇怪的php输出,该输出在以前的主机上运行良好。 php连接: php数据库调用: html格式的输出: '; } echo“”;echo“”;如果($row['priceMax']){echo'';}elseif($row['price']){echo'';}$firstRow=0;}}? 有人能解释这里到底出了什么问题吗?我不知

  • 0.9.2 新版功能. 封装字符串,提供 ANSI 色彩输出的函数。 本模块中的所有函数均返回包裹对应色彩 ANSI 字符的 text 字符串。 例如,在支持 ANSI 的终端中打印绿色文字: from fabric.colors import green print(green("This text is green!")) 这些函数返回值都是修改后的字符串,因此你也可以嵌套使用它们: fro

  • 这个程序应该做什么, 我希望它显示一个空白屏幕,直到我在键盘上点击任何字符。但是它做的事情很奇怪。它显示我按的任何东西。它永远不会终止,直到我按下回车键。 据我所知,getchar()应该只读取一个字符。它不应该输出任何东西。 为什么它打印我输入的每个字符? 编辑: 为什么 getchar() 在读取一个字符后不停止,例如在这段代码中: 程序应在读取一个字符后打印完成。

  • 我正在为两个3位数的乘积生成的最大回文编制程序。但程序给出的结果是999*999=998001有人能说出这个代码中的错误吗? 程序-

  • 问题内容: 我的朋友有一个小问题,我已不知所措。他编写了一个简单的(在学校就读到的)QuickSort算法,它产生了StackOverflow错误。我知道这意味着它在某处多次调用自身递归,但是我无法获得逻辑错误- 请帮助我! 这是代码(我在这里省略了一些代码,仅是为了在2个文本区域中显示它): 它的名称如下: 但是,如果我们将其称为2个数字相同,则不会产生溢出。 如果需要更多代码,这是pasteb

  • 我正在尝试制作一个程序,让很多人进入ArrayList,然后从中随机选择一个名字。代码运行正常,但请求名称输入的字符串在第一次运行时会显示两次。知道为什么会这样吗? 我希望它显示的内容:输入名称:。。。。。。 显示内容:输入名称:输入名称:。。。。。。