static StringDoubleMap test(int n, int range) {
    // Generate random data
    Random rand = new Random();
    Set<Integer> set = new HashSet<Integer>();
    for (int i = 0; i < n; i++) set.add(rand.nextInt(range));

    // Make the map
    StringDoubleMap map = new StringDoubleMap(0);
    // map.switchToSortedList();
    for (int x : set) {
      map.put("" + x, 1.0 * x);
    }

    // System.out.println("here");
    check(set, map);
    map.switchToSortedList();
    check(set, map);
    map.switchToHashTable();
    check(set, map);

    map.lock();
    for (int x : set) map.put("" + x, 1.0 * x);

    assert set.size() == map.size();
    return map;
  }
 // Return a map with only keys in the set
 public StringDoubleMap restrict(Set<String> set) {
   StringDoubleMap newMap = new StringDoubleMap();
   newMap.mapType = mapType;
   if (mapType == MapType.SORTED_LIST) {
     newMap.allocate(getCapacity(num, false));
     for (int i = 0; i < keys.length; i++) {
       if (set.contains(keys[i])) {
         newMap.keys[newMap.num] = keys[i];
         newMap.values[newMap.num] = values[i];
         newMap.num++;
       }
     }
   } else if (mapType == MapType.HASH_TABLE) {
     for (int i = 0; i < keys.length; i++)
       if (keys[i] != null && set.contains(keys[i])) newMap.put(keys[i], values[i]);
   }
   newMap.locked = locked;
   return newMap;
 }
 static void check(Set<Integer> set, StringDoubleMap map) {
   for (int x : set) {
     double value = map.getSure("" + x);
     assert value == 1.0 * x;
   }
   for (StringDoubleMap.Entry e : map) {
     int x = Integer.parseInt(e.getKey());
     assert set.contains(x);
     assert e.getValue() == 1.0 * x;
   }
 }
 // If keys are locked, we can share the same keys.
 public StringDoubleMap copy() {
   StringDoubleMap newMap = new StringDoubleMap();
   newMap.mapType = mapType;
   newMap.locked = locked;
   newMap.num = num;
   newMap.keys = locked ? keys : (String[]) keys.clone(); // Share keys!
   newMap.values = (double[]) values.clone();
   return newMap;
 }
  public static void main(String[] args) throws Exception {
    // Test
    int T = 200;
    int n = 10000;
    if (args[0].equals("ser")) {
      StringDoubleMap map = test(10000, 10000);
      map.locked = false; // Cheat
      map.switchToSortedList();

      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("map"));
      out.writeObject(map);
      out.close();

      ObjectInputStream in = new ObjectInputStream(new FileInputStream("map"));
      StringDoubleMap map2 = (StringDoubleMap) in.readObject();
      in.close();

      assert map.size() == map2.size();
      for (StringDoubleMap.Entry e : map) {
        assert map2.getSure(e.getKey()) == e.getValue();
      }
    } else if (args[0].equals("test")) {
      for (int i = 0; ; i++) {
        System.out.println("test " + i);
        test(10000, 10000);
      }
    } else if (args[0].equals("sdm")) {
      StringDoubleMap map = new StringDoubleMap();

      for (int q = 0; q < T; q++) {
        // System.out.println(q);
        for (int i = 0; i < n; i++) {
          // if(q > 0) System.out.println("put " + i);
          map.put(i + "key" + i, i + q);
          // map.debugDump();
          // if(q == 1 && i == 1000)
          // map.switchToHashTable();
        }
        if (q == 0) {
          map.switchToSortedList();
          // map.repCheck();
          // map.lock();
          map.debugDump();
        }
      }
    } else {
      HashMap<String, Double> omap = new HashMap<String, Double>();
      for (int q = 0; q < T; q++) {
        for (int i = 0; i < n; i++) {
          omap.put(i + "key" + i, 1.0 + i + q);
        }
      }
    }

    /*map.switchToSortedList();
    map.debugDump();

    map.switchToHashTable();
    map.debugDump();

    map.switchToSortedList();
    map.debugDump();

    for(Entry e : map)
      System.out.println(e.getKey() + " => " + e.getValue());*/
  }