FastArrayListはforEach()に対応していない

OpenJDK11で、Apache Commons Collections 3系に含まれるFastArrayListに対して、forEach()を行うと処理が行われない。

List<String> list = new FastArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");

StringBuilder sb = new StringBuilder();
list.forEach(e -> sb.append(e));

// xxが出力される
System.out.println("x" + sb.toString() + "x");

原因

FastArrayListはforEach()をオーバーライドしていないので、親であるArrayListのforEach()が実行される。

@Override
public void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    final int expectedModCount = modCount;
    final Object[] es = elementData;
    final int size = this.size;
    for (int i = 0; modCount == expectedModCount && i < size; i++)
        action.accept(elementAt(es, i));
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

ループ条件のmodCountはAbstractListで宣言されている。

protected transient int modCount = 0;

また、sizeはArrayListで宣言されている。

private int size;

これらはArrayList#add(E)ではインクリメントされるが、FastArrayList#add(Object)ではインクリメントされない。(sizeはアクセスできないし)

対処

匿名クラスでforEach()をオーバーライドする。

List<String> list = new FastArrayList() {
    public void forEach(Consumer action) {
        Objects.requireNonNull(action);
        for (Object t : this) {
            action.accept(t);
        }
    };
};
list.add("aaa");
list.add("bbb");
list.add("ccc");

StringBuilder sb = new StringBuilder();
list.forEach(e -> sb.append(e));

// xaaabbbcccxが出力される
System.out.println("x" + sb.toString() + "x");