final V doRemove(Object okey,Object value){
  Comparable<? super K> key=comparable(okey);
  for (; ; ) {
    Node<K,V> b=findPredecessor(key);
    Node<K,V> n=b.next;
    for (; ; ) {
      if (n == null)       return null;
      Node<K,V> f=n.next;
      if (n != b.next)       break;
      Object v=n.value;
      if (v == null) {
        n.helpDelete(b,f);
        break;
      }
      if (v == n || b.value == null)       break;
      int c=key.compareTo(n.key);
      if (c < 0)       return null;
      if (c > 0) {
        b=n;
        n=f;
        continue;
      }
      if (value != null && !value.equals(v))       return null;
      if (!n.casValue(v,null))       break;
      if (!n.appendMarker(f) || !b.casNext(n,f))       findNode(key);
 else {
        findPredecessor(key);
        if (head.right == null)         tryReduceLevel();
      }
      return (V)v;
    }
  }
}

final V doRemove ( Object okey , Object value ) { Comparable < ? super K > key = comparable ( okey ) ; for ( ; ; ) { Node < K , V > b = findPredecessor ( key ) ; Node < K , V > n = b . next ; for ( ; ; ) { if ( n == null ) return null ; Node < K , V > f = n . next ; if ( n != b . next ) break ; Object v = n . value ; if ( v == null ) { n . helpDelete ( b , f ) ; break ; } if ( v == n || b . value == null ) break ; int c = key . compareTo ( n . key ) ; if ( c < 0 ) return null ; if ( c > 0 ) { b = n ; n = f ; continue ; } if ( value != null && ! value . equals ( v ) ) return null ; if ( ! n . casValue ( v , null ) ) break ; if ( ! n . appendMarker ( f ) || ! b . casNext ( n , f ) ) findNode ( key ) ; else { findPredecessor ( key ) ; if ( head . right == null ) tryReduceLevel ( ) ; } return ( V ) v ; } } }
main deletion method . locates node , nulls value , appends a deletion marker , unlinks predecessor , removes associated index nodes , and possibly reduces head index level . index nodes are cleared out simply by calling findpredecessor . which unlinks indexes to deleted nodes found along path to key , which will include the indexes to this node . this is done unconditionally . we can ' t check beforehand whether there are index nodes because it might be the case that some or all indexes hadn ' t been inserted yet for this node during initial search for it , and we ' d like to ensure lack of garbage retention , so must call to be sure .
