Is there performance gain using .replace () instead of .put () in a Map?

2

There is some performance gain using the .replace() method instead of using .put() in a Map .

Studying Maps I noticed that the .put() and .replace() method have practically the same function. I made a simple code and tried it and the result was the same in both cases:

public static HashMap<String, String> Lista = new HashMap<String, String>();

public void methodTeste(String teste, String outra) {
    if (Lista.containsKey(teste)) {
        Lista.replace(teste, outra);
    } else {
        Lista.put(teste, outro);
    }
}

public void methodTeste(String teste, String outra) {
    Lista.put(teste, outro);
}

Which of the two codes will perform best?

    
asked by anonymous 31.07.2018 / 20:26

4 answers

1

After several tests I came to a conclusion: .replace should only be used when you are sure that the KEY already exists. If you are not sure of the existence of KEY (same as my case) it is more advantageous to use the right .put.

In the test where the KEY existence was right and there was no need for checks the .replace easily won:

public static HashMap<String, String> Lista = new HashMap<>();

private static void methodTeste1(String teste, String outra) {
    for (int i = 0; i < 100000; i++) {
        Lista.replace(teste, outra);    
    }
}

private static void methodTeste2(String teste, String outra) {
    for (int i = 0; i < 100000; i++) {
        Lista.put(teste, outra);
    }
}

public static void main(String[] args) {
    long inicio, fim;
    Lista.put("antonio", "antonio");

    inicio = System.currentTimeMillis();
    methodTeste1("antonio", "antonio");
    fim = System.currentTimeMillis();
    System.out.println("Replace: " + (fim-inicio)  + " ms");

    inicio = System.currentTimeMillis();
    methodTeste2("antonio", "antonio");
    fim = System.currentTimeMillis();
    System.out.println("Put: " + (fim-inicio) + " ms");
}
In the test where the existence of the KEY was not certain and we were forced to make checks .put obtained a significantly greater performance:

public static HashMap<String, String> Lista = new HashMap<>();

private static void methodTeste1(String teste, String outra) {
    for (int i = 0; i < 100000; i++) {
        if (Lista.containsKey("antonio")) {
            Lista.replace(teste, outra);
        } else {
            Lista.put(teste, outra);
        }
    }
}

private static void methodTeste2(String teste, String outra) {
    for (int i = 0; i < 100000; i++) {
        Lista.put(teste, outra);
    }

}

public static void main(String[] args) {
    long inicio, fim;

    inicio = System.currentTimeMillis();
    methodTeste1("antonio", "antonio");
    fim = System.currentTimeMillis();
    System.out.println("Replace: " + (fim-inicio)  + " ms");

    inicio = System.currentTimeMillis();
    methodTeste2("antonio", "antonio");
    fim = System.currentTimeMillis();
    System.out.println("Put: " + (fim-inicio) + " ms");
}

Conclusion: .replace has performance greater than .put but everything will depend on the situation.

    
31.07.2018 / 21:21
5

replace() is more efficient in cases where there is no key being used in it. It can only replace a value of an existing key, it performs nothing if it does not have the key. However, the put() will put a value there, if there is a key it will be equal to replace() , but if it does not exist you will have to create the key on the map, which has extra cost.

But performance should not be considered, the important thing is the semantics you want to give, they give different results under certain circumstances as shown above, so use what you need.

In this example, the test does not make sense (obviously the first one will be slower, it does much more and gives a different result from the second, it does not make sense to compare these two things ). If you only want to change the value if the key exists and do not create a new one, use replace() . To get the same result with put() would have to do so:

if (Lista.containsKey(teste)) lista.put(teste, outro);

which is the same as:

lista.replace(teste, outra);

Documentation .

The appropriate test would look like this:

import java.util.*;

class Ideone {
    public static HashMap<String, String> lista = new HashMap<>();

    private static void Put(String teste, String outra) {
        for (int i = 0; i < 100000; i++) if (lista.containsKey("antonio")) lista.put(teste, outra);
    }

    private static void Replace(String teste, String outra) {
        for (int i = 0; i < 100000; i++) lista.replace(teste, outra);
    }

    public static void main(String[] args) {
        long inicio = System.currentTimeMillis();
        Put("antonio", "antonio");
        System.out.println("Put: " + (System.currentTimeMillis() - inicio)  + " ms");
        inicio = System.currentTimeMillis();
        Replace("antonio", "antonio");
        System.out.println("Replace: " + (System.currentTimeMillis() - inicio) + " ms");
    }
}

See running on ideone . And in Coding Ground . Also I placed GitHub for future reference .

    
31.07.2018 / 20:46
2

If you use put () with a key that exists, it will be overwritten. The map does not contain duplicate keys. You use replace to override and put to add, but put does both.

    
31.07.2018 / 20:59
0

Make this test simple:

public static HashMap<String, String> Lista = new HashMap<>();

private static void methodTeste1(String teste, String outra) {
    for (int i = 0; i < 100000; i++) {
        if (Lista.size() > 0) {
            Lista.replace(teste, outra);
        } else {
            Lista.put(teste, outra);
        }
    }
}

private static void methodTeste2(String teste, String outra) {
    for (int i = 0; i < 100000; i++) {
        Lista.put(teste, outra);
    }

}

public static void main(String[] args) {
    long inicio, fim;

    inicio = System.currentTimeMillis();
    methodTeste1("antonio", "antonio");
    fim = System.currentTimeMillis();
    System.out.println("Replace: " + (fim-inicio)  + " ms");


    inicio = System.currentTimeMillis();
    methodTeste2("antonio", "antonio");
    fim = System.currentTimeMillis();
    System.out.println("Put: " + (fim-inicio) + " ms");
}
    
31.07.2018 / 20:46