JDK-8157110 : Behavioural change with extended ArrayList class
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 7,8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2016-05-17
  • Updated: 2021-03-03
  • Resolved: 2016-05-26
Related Reports
Relates :  
Description
ArrayList Iterator behavior has been changed from jdk6 to jdk7.

Create and compile the below 3 class and then run Main.java. 
Using JDK6 it prints the element but JDK7 no element is printed.

// DynamicResult.java
public class DynamicResult {
	public Object next() {
		return Math.random() * ( 1000 - 1 );
	}
}


// DynamicArrayList.java
import java.util.ArrayList;

public class DynamicArrayList extends ArrayList{
	
	private int size;
	private DynamicResult dynValues; 

	public DynamicArrayList(DynamicResult result, int size){
		this.dynValues = result;
		this.size = size;
	}
    
	@Override
	public int size() {
		return super.size() + size;
	}

	@Override
	public Object get(int index) {
		if(index < size){
			return dynValues.next();
		} else {
			return super.get(index - size);
		}
	}
}

// Main.java
import java.util.ArrayList;
import java.util.Iterator;

public class Main {
	public static void main(String [] args){
		System.out.println("This code does not work in JDK7 but works in JDK6");
		System.out.println("Print 1 element as size is 1");
		ArrayList list = new DynamicArrayList(new DynamicResult(), 1);
		
		Iterator iter = list.iterator();
		if(iter !=null && iter.hasNext()){
		    System.out.println(iter.next());
		}
	}
}

Comments
More on this issue in JDK-8158160.
31-05-2016

As per the final update from development group here is the summary: This is a change in behavior between JDK 6 and JDK 7. It is not something that we can realistically change again, as it would potentially have negative affects on applications, running on JDK 7 and later, making assumptions about the present behavior. Implementing a composite iterator, like shown in the below example will work for JDK 6 and future JDK releases. [Instead of DynamicArrayList.java class in the bug description, use the below class DynamicArrayListWithIterator.java to achieve the required result]. import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; public class DynamicArrayListWithIterator extends ArrayList{ private int size; private DynamicResult dynValues; public DynamicArrayListWithIterator(DynamicResult result, int size){ this.dynValues = result; this.size = size; } @Override public Iterator iterator() { return new DynamicIterator(); } @Override public int size() { return super.size() + size; } @Override public Object get(int index) { if(index < size){ return dynValues.next(); } else { return super.get(index - size); } } private class DynamicIterator implements Iterator { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } @SuppressWarnings("unchecked") public Object next() { checkForComodification(); int i = cursor; if (i >= size()) throw new NoSuchElementException(); cursor = i + 1; lastRet = i; return get(i); } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { DynamicArrayListWithIterator.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } }
26-05-2016