0

My Java code:

        if(wins.containsKey(winner)) {
            int currentCount = wins.get(winner);
            wins.remove(winner);

            wins.put(winner, currentCount + 1);
        } else {
            wins.put(winner, 1);
        }

This was my alternative to something I can do in PHP and even C#:

if(isset($something[$key])) {
    $something[$key]++;
} else {
    $something[$key] = 1;
}

This is going to be used in a high number of iterations in a for loop so I would like to consider performance. Is this whole remove() then puts() business killing the performance? What is an alternative?

1
  • Well, for one thing, wins isn't an array (as the title states). With arrays in Java, you can happily use []. Commented Sep 30, 2013 at 19:02

3 Answers 3

5

Your code can be replaced to:

if(wins.containsKey(winner)) {
    wins.put(winner, wins.get(winner) + 1);
} else {
    wins.put(winner, 1);
}

No need to remove the entry. When you add another entry in the map with same key, it will overwrite the existing one.

Sign up to request clarification or add additional context in comments.

3 Comments

It's still performing a containment check, a get, a put and a boxing operation for every iteration. While it's almost certainly not a problem, it's not as fast as it could be.
@JonSkeet. Hmm. The only real issue is unboxing and boxing. Rest we can't avoid IMO. Not a real performance gain over the original code though.
You can definitely avoid doing a containment check followed by a get (see the second part of my answer) and you can avoid doing a put other than for "new" entries (see the first part).
1

The way I usually do this to be as efficient as possible is:

Integer val = wins.get(winner);
wins.put(winner,val == null ? 1 : (val + 1));

This is very clean to me and avoids the extra hash lookup to "get" the val after you know it's already in there from the contains.

Comments

1

Firstly, I strongly suspect that this isn't going to be a performance bottleneck. As ever, test the simplest code that works before you use more complicated code.

You could use AtomicInteger instead of Integer as the value type of your map. That would allow you to mutate the wrapped value, rather than replacing the whole entry. Then you'd have:

if(wins.containsKey(winner)) {
    wins.get(winner).incrementAndGet();
} else {
    wins.put(winner, new AtomicInteger(1));
}

If you can stick with Integer, you could still optimize your code further:

Integer previousValue = wins.get(winner);
int newValue = previousValue == null ? 1 : (int) previousValue + 1;
wins.put(winner, newValue);

Now there is exactly one get and one put operation on each iteration.

1 Comment

Liked the 2nd version. Didn't think of that way. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.