| 334 | } |
| 335 | |
| 336 | public V compute(int key, @NotNull IntObjectFunction<V> op) { |
| 337 | if (key == 0) { |
| 338 | final V oldV = zeroValue; |
| 339 | final V v = op.apply(key, oldV); |
| 340 | if (v != oldV) { |
| 341 | zeroValue = v; |
| 342 | if (v == null) { |
| 343 | if (hasZeroValue) { |
| 344 | hasZeroValue = false; |
| 345 | size--; |
| 346 | } |
| 347 | } else if (!hasZeroValue) { |
| 348 | hasZeroValue = true; |
| 349 | size++; |
| 350 | } |
| 351 | } |
| 352 | return v; |
| 353 | } |
| 354 | final int[] kt = keyTable; |
| 355 | final V[] vt = valueTable; |
| 356 | for (int i = hash(key), m = mask; ; i = (i + 1) & m) { |
| 357 | final int k = kt[i]; |
| 358 | if (k == key) { |
| 359 | final V oldV = vt[i]; |
| 360 | final V v = op.apply(key, oldV); |
| 361 | if (v != oldV) { |
| 362 | vt[i] = v; |
| 363 | if (v == null) { |
| 364 | for (int j = (i + 1) & m; (key = kt[j]) != 0; j = (j + 1) & m) { |
| 365 | final int h = hash(key); |
| 366 | if (((j - h) & m) > ((i - h) & m)) { |
| 367 | kt[i] = key; |
| 368 | vt[i] = vt[j]; |
| 369 | i = j; |
| 370 | } |
| 371 | } |
| 372 | kt[i] = 0; |
| 373 | vt[i] = null; |
| 374 | size--; |
| 375 | } |
| 376 | } |
| 377 | return v; |
| 378 | } |
| 379 | if (k == 0) { |
| 380 | final V v = op.apply(key, null); |
| 381 | if (v != null) { |
| 382 | kt[i] = key; |
| 383 | vt[i] = v; |
| 384 | if (++size >= threshold) |
| 385 | resize(kt.length << 1); |
| 386 | } |
| 387 | return v; |
| 388 | } |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | public @Nullable V remove(int key) { |
| 393 | if (key == 0) { |