【问题标题】:Why does LinkedList.indexOf() return -1 if the object is contained in the list?如果对象包含在列表中,为什么 LinkedList.indexOf() 返回 -1?
【发布时间】:2014-12-06 03:48:31
【问题描述】:

我已经声明了一个 LinkedList,其中 Frame 是我的列表项。

private LinkedList<Frame> linkedList = new LinkedList<Frame>();

我意识到,当我测试 indexOf -1 时,即使列表包含查询的项目也会返回。文档说明“(...) 如果此列表不包含该元素,则为 -1。”。

https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#indexOf(java.lang.Object)

看看这些奇怪的结果:

linkedList.size() -> 1
linkedList.get(0) -> frame
linkedList.contains(linkedList.get(0)) -> false
linkedList.indexOf(linkedList.get(0)) -> -1

我忽略了什么吗?有什么想法吗?

我正在从各个线程访问列表而没有同步。这会导致问题吗?

--

日志(见下文):

12-05 20:30:00.101  16446-16461/cc.closeup I/System.out﹕ **** TEST              0
12-05 20:30:00.301  16446-16476/cc.closeup I/System.out﹕ **** TEST              -1
12-05 20:30:00.856  16446-16461/cc.closeup I/System.out﹕ **** TEST              0
12-05 20:30:01.051  16446-16476/cc.closeup I/System.out﹕ **** TEST              -1
12-05 20:30:01.601  16446-16461/cc.closeup I/System.out﹕ **** TEST              0
12-05 20:30:01.801  16446-16476/cc.closeup I/System.out﹕ **** TEST              -1
12-05 20:30:02.356  16446-16461/cc.closeup I/System.out﹕ **** TEST              0
12-05 20:30:02.551  16446-16476/cc.closeup I/System.out﹕ **** TEST              -1
12-05 20:30:03.101  16446-16461/cc.closeup I/System.out﹕ **** TEST              0
12-05 20:30:03.301  16446-16476/cc.closeup I/System.out﹕ **** TEST              -1

【问题讨论】:

  • 你的Frame类型是如何实现equals(Object)的?
  • 一点也不。我需要实施它吗?
  • 并非如此,它将继承 Object 的实现,该实现应该适用于您展示的 containsindexOf 情况。请给我们一个可重现的例子。
  • 您是否正确同步了所有内容?读写?
  • 您还需要将您对列表的访问权限放在同步块中,例如: synchronized(linkedList) { //您的代码 }

标签: java linked-list


【解决方案1】:

仔细查看containsindexOf 的javadocs。它声明这些方法通过使用equals 方法确定元素是否在集合中。

如果containsindexOf 说“它不存在”,那么列表中存在的对象与您正在测试的对象不同...根据对象的@ 实现987654327@.


另一种可能性是您正在从不同的线程访问/更新集合,并且您没有正确同步。这可能会导致一个线程看到列表的陈旧或不一致版本。

如果我同步列表本身,你认为我没问题吗?

    Collections.synchronizedList(new LinkedList<>())

如果您通过同步列表执行所有操作并且不使用迭代器,那么每个单独的操作将是线程安全的和原子的。然而:

  • “同步列表”的迭代器未同步,并且
  • 如果您需要以原子方式同步/执行一系列操作,这将无济于事。

例如:

    List<Integer> l =  Collections.synchronizedList(new LinkedList<>());

    // Make the list visible to other threads ...

    for (int i = 0; i < l.size(); i++) {
        Integer ii = l.get(i);
        ...
    }

虽然l.size() 将始终给出当前大小,但大小可能l.size()l.get(i) 调用之间发生变化,可能会导致异常。

简而言之...Collections.synchronizedList(...) 不是所有涉及列表的线程安全问题的解决方案。你仍然需要考虑你在做什么。

【讨论】:

  • “另一种可能性是您正在从不同的线程访问/更新集合,并且您没有正确同步。这可能导致一个线程看到列表的陈旧或不一致的版本。” -> 这正是发生的事情。
  • 即使已经回答了这个问题,这里有一个链接很好地解释了不同线程如何看到同一变量的不同版本:tutorials.jenkov.com/java-concurrency/volatile.html - 也非常适合学习并发性.
猜你喜欢
  • 2020-11-13
  • 2018-06-14
  • 2013-05-12
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多