Oliver Hausler
Oliver Hausler

Reputation: 4977

Why does LinkedList.indexOf() return -1 if the object is contained in the list?

I have declared a LinkedList, where Frame is my list item.

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

I realized that when I test for indexOf -1 is returned even though the list contains the queried item. Documentation states "(...) or -1 if this list does not contain the element.".

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

Look at these strange results:

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

Did I overlook anything? Any ideas what's going on?

I am accessing the list from various threads without synchronization. Could this have caused the problem?

--

Log (see below):

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

Upvotes: 1

Views: 110

Answers (1)

Stephen C
Stephen C

Reputation: 718886

Look carefully at the javadocs for contains and indexOf. It states that the methods determine if an element is in the collection by using the equals method.

If contains and indexOf are saying "it isn't there" then the object that is present in the list is a different one to the one you are testing for ... according to the object's implementation of equals(Object).


The other possibility is that you are accessing / updating the collection from different threads, and you haven't synchronized properly. This can lead to one thread seeing a stale or inconsistent version of the list.

Would you think I am fine if I synchronize the list itself?

    Collections.synchronizedList(new LinkedList<>())

If you perform all operations via the synchronized list AND you don't use the iterator, then each individual operation will be thread-safe and atomic. However:

  • the iterator of a "synchronized list" is not synchronized, and
  • this doesn't help if you need a sequence of operations to be synchronized / performed atomically.

For example:

    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);
        ...
    }

While l.size() will always give the current size, the size might change between the l.size() and l.get(i) calls, potentially resulting in an exception.

In short ... Collections.synchronizedList(...) is NOT a solution for all thread-safety problems involving lists. You STILL need to think about what you are doing.

Upvotes: 1

Related Questions