protected < T > T pickPluck ( Iterable < ? extends T > iterable , T ifEmpty , boolean remove ) { if ( iterable instanceof Collection ) { // optimized path for Collection @ SuppressWarnings ( "unchecked" ) Collection < ? extends T > coll = ( Collection < ? extends T > ) iterable ; int size = coll . size ( ) ; if ( size == 0 ) { return ifEmpty ; } if ( coll instanceof List ) { // extra-special optimized path for Lists @ SuppressWarnings ( "unchecked" ) List < ? extends T > list = ( List < ? extends T > ) coll ; int idx = _r . nextInt ( size ) ; if ( remove ) { // ternary conditional causes warning here with javac 1.6, :( return list . remove ( idx ) ; } return list . get ( idx ) ; } // for other Collections, we must iterate Iterator < ? extends T > it = coll . iterator ( ) ; for ( int idx = _r . nextInt ( size ) ; idx > 0 ; idx -- ) { it . next ( ) ; } try { return it . next ( ) ; } finally { if ( remove ) { it . remove ( ) ; } } } if ( ! remove ) { return pick ( iterable . iterator ( ) , ifEmpty ) ; } // from here on out, we're doing a pluck with a complicated two-iterator solution Iterator < ? extends T > it = iterable . iterator ( ) ; if ( ! it . hasNext ( ) ) { return ifEmpty ; } Iterator < ? extends T > lagIt = iterable . iterator ( ) ; T pick = it . next ( ) ; lagIt . next ( ) ; for ( int count = 2 , lag = 1 ; it . hasNext ( ) ; count ++ , lag ++ ) { T next = it . next ( ) ; if ( 0 == _r . nextInt ( count ) ) { pick = next ; // catch up lagIt so that it has just returned 'pick' as well for ( ; lag > 0 ; lag -- ) { lagIt . next ( ) ; } } } lagIt . remove ( ) ; // remove 'pick' from the lagging iterator return pick ; }
Shared code for pick and pluck .