@Override
 public V remove(Object key) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   segments[segment].remove(h, (K) key);
   return null;
 }
 @Override
 public V put(K key, V value) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   segments[segment].put(h, key, value, true, true);
   return null;
 }
 @Override
 public V replace(@NotNull K key, @NotNull V value) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   segments[segment].put(h, key, value, true, false);
   return null;
 }
 @Override
 public boolean replace(@NotNull K key, @NotNull V oldValue, @NotNull V newValue) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   Segment<K, V> segment2 = segments[segment];
   //noinspection SynchronizationOnLocalVariableOrMethodParameter
   synchronized (segment2) {
     V value2 = get(key);
     if (value2 != null && oldValue.equals(value2)) {
       segment2.put(h, key, newValue, true, true);
       return true;
     }
     return false;
   }
 }
 @Override
 public boolean remove(@NotNull Object key, Object value) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   Segment<K, V> segment2 = segments[segment];
   //noinspection SynchronizationOnLocalVariableOrMethodParameter
   synchronized (segment2) {
     V value2 = get(key);
     if (value2 != null && value.equals(value2)) {
       segment2.remove(h, (K) key);
       return true;
     }
     return false;
   }
 }
 @Override
 public boolean containsKey(Object key) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   return segments[segment].containsKey(h, (K) key);
 }
 @Override
 public V get(K key, V value) {
   long h = hasher.hash(key);
   int segment = hasher.getSegment();
   return segments[segment].get(h, key, value);
 }