collections - Why is toArray implemented like this in java? -
as see source code of: java.util.abstractcollection.toarray(), implemented this:
public object[] toarray() { // estimate size of array; prepared see more or fewer elements object[] r = new object[size()]; iterator<e> = iterator(); (int = 0; < r.length; i++) { if (! it.hasnext()) // fewer elements expected return arrays.copyof(r, i); r[i] = it.next(); } return it.hasnext() ? finishtoarray(r, it) : r; } private static <t> t[] finishtoarray(t[] r, iterator<?> it) { int = r.length; while (it.hasnext()) { int cap = r.length; if (i == cap) { int newcap = cap + (cap >> 1) + 1; // overflow-conscious code if (newcap - max_array_size > 0) newcap = hugecapacity(cap + 1); r = arrays.copyof(r, newcap); } r[i++] = (t)it.next(); } // trim if overallocated return (i == r.length) ? r : arrays.copyof(r, i); }
as see,the implementation not easy understand, question :
- what when collection's elements change (size not changed) during iteration? guess iterator may kind of snapshot.
- what when collection's size changed? wonder if can work correctly.
as see,the implementation not easy understand, question :
- what when collection's elements change (size not changed) during iteration? guess iterator may kind of snapshot.
- what when collection's size changed? wonder if can work correctly.
the implementation way because it's intended handle case iterator returns different number of elements size()
. can occur if collection's size changes during iteration. destination array allocated based on size()
, , in optimistic case size doesn't change, it's pretty straightforward. complexity of code comes in actual number of elements returned iterator differs initial value returned size()
. if actual number of elements smaller, elements copied smaller array of right size. if actual number bigger, elements copied larger array, , more elements iterated. array repeatedly reallocated larger if fills up, until iteration completes.
to first question, iterator doesn't take snapshot of elements. depends on actual collection implementation. collections (such copyonwritearraylist
) have snapshot semantics, if collection modified, modification won't visible iterator. in case number of elements reported iterator match size()
, no array reallocation necessary.
other collection implementations have different policies happens if collection modified during iteration. fail-fast means they'll throw concurrentmodificationexception
. others weakly consistent means modifications might or might not visible iterator.
this applies second question. if collections size changes during iteration, , if collection's iterator supports (i.e., it's not fail-fast), code here handle different number of elements coming out of iterator reported size()
.
an example can occur concurrentskiplistset
. class's iterator weakly consistent, , inherits toarray()
method abstractcollection
. thus, while toarray()
iterating set in order gather elements destination array, it's entirely legal thread modify set, possibly changing size. can cause iterator report different number of elements initial value returned size()
, cause array reallocation code in toarray()
executed.
Comments
Post a Comment