private void resize ( Object [ ] oldTable , int newSize ) { int oldCapacity = oldTable . length ; int end = oldCapacity - 1 ; Object last = arrayAt ( oldTable , end ) ; if ( this . size ( ) < ( ( end * 3 ) >> 2 ) && last == RESIZE_SENTINEL ) { return ; } if ( oldCapacity >= MAXIMUM_CAPACITY ) { throw new RuntimeException ( "max capacity of map exceeded" ) ; } ResizeContainer resizeContainer = null ; boolean ownResize = false ; if ( last == null || last == RESIZE_SENTINEL ) { synchronized ( oldTable ) // allocating a new array is too expensive to make this an atomic operation { if ( arrayAt ( oldTable , end ) == null ) { setArrayAt ( oldTable , end , RESIZE_SENTINEL ) ; resizeContainer = new ResizeContainer ( allocateTable ( newSize ) , oldTable . length - 2 ) ; setArrayAt ( oldTable , end , resizeContainer ) ; ownResize = true ; } } } if ( ownResize ) { this . transfer ( oldTable , resizeContainer ) ; Object [ ] src = this . table ; while ( ! TABLE_UPDATER . compareAndSet ( this , oldTable , resizeContainer . nextArray ) ) { // we're in a double resize situation; we'll have to go help until it's our turn to set the table if ( src != oldTable ) { this . helpWithResize ( src ) ; } } } else { this . helpWithResize ( oldTable ) ; } }
newSize must be a power of 2 + 1