When I try to do some performance test for Java List/Map, I find a strange performance result.
My test logic split into data prepare and map put operation, the separated data prepare process is object to calculate map operation cost correct.
I can understand the different String creation methods result into different performance result, but the strange thing was: use of one specific hard-coded String results in the worst performance.
Why this result is so.
Here is the test code, performance result is included in test case method comment
package cn.codeworks.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import org.junit.Test;
public class TreeMapPerformanceTest {
  private static final int dataSize = 1000 * 1000;
  static class Pair {
    private final Integer key;
    private final String value;
    public Pair(Integer key, String value) {
      this.key = key;
      this.value = value;
    }
    public Integer getKey() {
      return key;
    }
    public String getValue() {
      return value;
    }
  }
  /**
   * time cost (3 times) = 196, 178, 186
   */
  @Test
  public void testPutPerformance_string_intern() {
    testPutPerformance((loc) -> new String("abc").intern());
  }
  /**
   * time cost (3 times) = 275, 317, 331
   */
  @Test
  public void testPutPerformance_string_new() {
    testPutPerformance((loc) -> new String("abc"));
  }
  /**
   * this case got bad performance
   * time cost (3 times) = 591, 565, 570
   */
  @Test
  public void testPutPerformance_string_hardcoded() {
    testPutPerformance((loc) -> "abc");
  }
  private void testPutPerformance(Function<Integer, String> stringCreateMethod) {
    // prepare data
    List<Pair> data = new ArrayList(dataSize);
    for (int i = 0; i < dataSize; i++) {
      Pair pair = new Pair(i, stringCreateMethod.apply(i));
      data.add(pair);
    }
    int size = data.size();
    // map operation
    Map<Integer, String> map = new TreeMap<>();
    long startTimeMillis = System.currentTimeMillis();
    for (int i = 0; i < size; i++) {
      Pair pair = data.get(i);
      map.put(pair.getKey(), pair.getValue());
    }
    long endTimeMillis = System.currentTimeMillis();
    System.out.println("time cost = " + (endTimeMillis - startTimeMillis));
  }
}
 
    