# indexOf with nested ArrayList

**URL:** https://discourse.processing.org/t/indexof-with-nested-arraylist/14272
**Category:** Coding Questions
**Created:** [September 29, 2019, 11:27am UTC](https://discourse.processing.org/t/indexof-with-nested-arraylist/14272 "2019-09-29T11:27:35Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![companje](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/companje/32/2418_2.png) [@companje](https://discourse.processing.org/u/companje)
#### Post date: [September 29, 2019, 11:27am UTC](https://discourse.processing.org/t/indexof-with-nested-arraylist/14272/1 "2019-09-29T11:27:35Z")

</div>

Hi there,

I’ve got some menu structure where I’m nesting ArrayLists like this `class Menu extends ArrayList<Menu>`. It gives me some really interesting results when I’m using `indexOf`. Somehow it looks like it’s doing a recursive `indexOf` (traversing down the tree). Is this normal? What do you think?  
When I override the `indexOf` function with my own code it works as I would expect.

```auto
Menu root = new Menu();

void setup() {  
  Menu a = root.addItem("a");
  Menu b = root.addItem("b");
  Menu c = root.addItem("c");
  Menu d = root.addItem("d");
  
  Menu b1 = b.addItem("b1");
  Menu b2 = b.addItem("b2");
  Menu b3 = b.addItem("b3");
  
  Menu b2x = b2.addItem("b2x");
  Menu b2y = b2.addItem("b2y");
  Menu b2z = b2.addItem("b2z");
  
  println(root.indexOf(b2z)); //returns 0 instead of -1
  println(b.indexOf(b2z)); //returns 0 instead of -1
  println(b2.indexOf(b2z)); //returns 0 instead of 2
}

class Menu extends ArrayList<Menu> {
  String title;

  Menu addItem(String title) {
    Menu m = new Menu();
    m.title = title;
    add(m);
    return m;
  }

  //when overriding indexOf it works like I would expect. 
  //int indexOf(Menu findMe) {
  // for (int i=0; i<size(); i++) {
  // if (get(i)==findMe) return i;
  // }
  // return -1;
  //}
}

```

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [September 29, 2019, 3:31pm UTC](https://discourse.processing.org/t/indexof-with-nested-arraylist/14272/2 "2019-09-29T15:31:25Z")

</div>

[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/util/AbstractList.html#equals(java.lang.Object)](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/util/AbstractList.html#equals(java.lang.Object))

---

<div class="post-metadata">

### Author: ![companje](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/companje/32/2418_2.png) [@companje](https://discourse.processing.org/u/companje)
#### Post date: [September 29, 2019, 6:02pm UTC](https://discourse.processing.org/t/indexof-with-nested-arraylist/14272/3 "2019-09-29T18:02:12Z")

</div>

Thanks. I read the documentation about the `equals` and `indexOf` function. But I still don’t understand why `indexOf` would return 0 instead of -1…

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [September 30, 2019, 7:14am UTC](https://discourse.processing.org/t/indexof-with-nested-arraylist/14272/4 "2019-09-30T07:14:11Z")

</div>

> [@companje](#):
>
> But I still don’t understand why **indexOf()** would return 0 instead of -1…

B/c an Object’s **equals()** method can have its own arbitrary rules to “determine” that another Object is “equal to” it:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object))

While your `@Override` **indexOf()** relies instead on the equality `==` operator:

> **[== (equality) / Reference](https://processing.org/reference/equality.html)**
>
> Determines if two values are equivalent. Please note the equality operator (==) is different from the assignment operator (=) and although they look similar, they have a different use. If you're compa…

A very peculiar behavior of Java’s `==` operator is that it always compare values, regardless whether they’re numbers or references (a.K.a. pointers or memory addresses).

So at your statement `if (get(i) == findMe) return i;`, it matches only when 1 of the stored Menu objects has the same memory address value stored in the _findMe_ parameter.

That is, when the loop finds out they’re exactly the very same object.

That only matches at `println(b2.indexOf(b2z));`, b/c _b2z_  
is indeed the 3rd (index 2) Menu object created by Menu _b2_: `Menu b2z = b2.addItem("b2z");`

Now back to the original **indexOf()**, why does it seem like that it always finds a match at index `0`?

Well, not always! Try out replacing _b2z_ in `println(root.indexOf(b2z));` w/ _b2_: `println(root.indexOf(b2));`

You’ll see it’s finally gonna log `-1` this time!

As stated before, the original **indexOf()** relies on the implementation of **equals()** from AbstractList:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/util/AbstractList.html#equals(java.lang.Object)](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/util/AbstractList.html#equals(java.lang.Object))

Actually you’d get the same behavior as your `@Override` **indexOf()** if you simply `@Override` **equals()**, comparing the passed Object to `this` using the `==` operator:

```auto
@Override boolean equals(final Object o) {
  return o == this;
}

```

According to original AbstractList::**equals()**:

> Compares the specified object with this list for equality. Returns `true` if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are _equal_ .

W/ the rules above in mind, let’s get into why `println(root.indexOf(b2z));` logs `0` rather than `-1`.

- Variable _root_ is a Menu list w/ **size()** = 4, w/ elements _a_, _b_, _c_ & _d_.
- Variable _b2z_ is a Menu list w/ **size()** = 0. It’s empty, so no elements.
- The 1st _root_ element at index `0` is _a_.
- Like _b2z_, _a_ is also a Menu list w/ **size()** = 0.
- Given both are empty lists, comparing each of their elements at their corresponding index position using their own **equals()** is completely skipped.
- Thus the Menu _a_ list is considered “equal to” Menu _b2z_ list at index `0` according to AbstractList::**equals()**'s condition rules.

---

<div class="post-metadata">

### Author: ![companje](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/companje/32/2418_2.png) [@companje](https://discourse.processing.org/u/companje)
#### Post date: [September 30, 2019, 8:22pm UTC](https://discourse.processing.org/t/indexof-with-nested-arraylist/14272/5 "2019-09-30T20:22:21Z")

</div>

Wow, thank you so much @GoToLoop for explaining this in so much detail. I now fully understand it.
