code: 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;
      }
docs: Shared code for pick and pluck.