-1

I want to:

  1. Add an entry to a ConcurrentHashMap, if there is no entry for the key, or
  2. Replace the value for the key, only if the current value is smaller.

I came up with the following code, but sine it has while (true), it looks scary to me :)

I wanted to check it with you guys. Do you think it is working?

// Input: map, k, t
while (true) {
    if (map.containsKey(k)) {
        current = map.get(k);
        if (current != null && current < t) {
            if (map.replace(k, current, t))
                break;
        } else if (current != null && current >= t) {
            break;
        }
    } else {
        pre = map.putIfAbsent(k, t);
        if (pre == null)
            break;
    }
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
Mohammad Roohitavaf
  • 439
  • 2
  • 6
  • 15
  • Did you try it? Did you run it in your IDE debugger and step through it one line at a time? Please do that, it will be much more educational than having someone tell you. And by the way, there's no need for the `while(true)` (or a loop of any kind) at all. – Jim Garrison Jul 20 '16 at 06:00
  • use `Map.entrySet()` for iterating – Vishal Vijayan Jul 20 '16 at 06:03
  • @JimGarrison why I don't need while (true)? Suppose a thread wants to write t, but the map already has the key, so it goes to the first If. then when it is replacing, the replace returns false, because the value has changed by another thread meanwhile to a value higher than current but smaller than t. Since the thread "wants to" write t (since t is higher), it needs to start over. – Mohammad Roohitavaf Jul 20 '16 at 15:41

1 Answers1

5

If you're using Java 8, you can use the merge method. It takes:

  • the key K to map to
  • a value V to use if there is not already a value at K
  • a BiFunction<K,K,V> F that combines any already-present value with V, and stores it at K

For your use case, you would have:

  • K: your key
  • V: the new value
  • F: a function that compares its two inputs, and returns the higher of the two

If there is not already a value at K, it'll just store V. Otherwise, it'll pass the new V and the old V to your function, and store the result at K. Since your function returns the highter of the two, this amounts to replacing the value iff it is higher than the previous value.

yshavit
  • 42,327
  • 7
  • 87
  • 124
  • 1
    OP is using `replace()` which was added in Java 8, so OP *is* using Java 8. – Andreas Jul 20 '16 at 06:42
  • Thank you, I will try use this method. By the way I am assigning the higher value not smaller. – Mohammad Roohitavaf Jul 20 '16 at 15:36
  • @MohammadRoohitavaf It should be one of the arguments that gets passed to that BiFunction. Is that not working? – yshavit Jul 20 '16 at 17:30
  • Yea, it is the first argument, Thanks ^_^. I wish we had a similar method for remove. I need that one too. I found that there is a remove function that remove only if the current value equals to a expected value, but we don't have any remove function if the current value is less than the new value. – Mohammad Roohitavaf Jul 20 '16 at 17:45