static void iterTest() {
    iterateFromTest();

    final ConcurrentDoubleOrderedListMap<String> map = new ConcurrentDoubleOrderedListMap<String>();
    for (int i = -1000; i < 1001; i++) {
      map.put(i, "" + i);
    }

    DoubleObjectIterator<String> iter = map.iterator(11, 20, true, true);
    double sum = 0;
    while (iter.hasNext()) {
      iter.next();
      sum += iter.key();
    }
    assert sum == (11 + 20) * 5 : "sum:" + sum + ", != " + (11 + 20) * 5;

    iter = map.iterator(-1000, 1, true, false);
    sum = 0;
    while (iter.hasNext()) {
      iter.next();
      sum += iter.key();
    }
    assert sum == -1000 * (1000 + 1) / 2;

    iter = map.iterator(-1000, -995, true, true);
    sum = 0;
    while (iter.hasNext()) {
      iter.next();
      sum += iter.key();
    }
    assert sum == -(1000 + 999 + 998 + 997 + 996 + 995);

    iter = map.iteratorFrom(995, true);
    sum = 0;
    while (iter.hasNext()) {
      iter.next();
      sum += iter.key();
    }
    assert sum == (995 + 996 + 997 + 998 + 999 + 1000);

    iter = map.iteratorTo(-995, false);
    sum = 0;
    while (iter.hasNext()) {
      iter.next();
      sum += iter.key();
    }
    assert sum == -(1000 + 999 + 998 + 997 + 996);

    map.doSanityCheck();
    map.clear();
    System.out.println("done");
  }
  static void parTest() {
    final int N = 100000;
    final ConcurrentDoubleOrderedListMap<String> map = new ConcurrentDoubleOrderedListMap<String>();
    final double[] keys = new double[N];

    final Random r = new Random();
    for (int i = 0; i < N; i++) {
      int x = r.nextInt();
      keys[i] = x;
      map.put(x, "" + x);
    }
    map.doSanityCheck();
    System.out.println("Start parallel...");

    long s = System.currentTimeMillis();
    for (int i = 0; i < N; i++) {
      map.get(keys[i]);
    }
    long e = System.currentTimeMillis();
    System.out.println("Exec time:" + (e - s) + "ms");

    final int nReader = 8;
    final int nReplacer = 4;
    final int nWriter = 4;
    final int nThread = nReader + nReplacer + nWriter;
    for (int i = 0; i < 5; i++) {
      ParUtil.parallel(
          nThread,
          new ParUtil.CallableBlock() {
            @Override
            public void call(int index) {
              if (index < nReader) {
                for (int j = 0; j < 35; j++) {
                  for (int i = index; i < N; i += nReader) {
                    String val = map.get(keys[i]);
                    assert val != null && val.equals("" + keys[i])
                        : "key:" + keys[i] + ", val:" + val;
                  }
                }
                // System.out.println("Finished reader thread:" + index);
              } else if (index < nReader + nReplacer) {
                for (int j = 0; j < 5; j++) {
                  for (int i = index; i < N; i += nReplacer) {
                    boolean replaced = map.replace(keys[i], "" + keys[i], "" + keys[i]);
                    assert replaced;
                  }
                }
                // System.out.println("Finished writer(replace) thread:" + index);
              } else {
                for (int i = 0; i < 2 * N; i++) {
                  int x = r.nextInt();
                  map.putAtomic(x, "" + x);
                }
                // System.out.println("Finished writer thread:" + index);
              }
            }
          });
      System.out.println("Finished all parallel... i:" + i);
      map.doSanityCheck();
    }
    /*
    System.out.println("Node.pool size:"+Node.pool.size());
    while(true) {
        Node n = Node.pool.poll();
        if (n==null) break;
        System.out.println("n.refcnt:"+n.refcnt);
    }
    System.out.println("fill ratio:"+map._fillRatio());
    */
  }