将数字拆分为不同的范围

时间:2013-02-08 05:48:14

标签: java hashmap concurrenthashmap

我正在尝试测量每个线程插入数据库所花费的时间。我已经在ConcurrentHashMap命名映射中捕获了所有这些性能数字,比如每个线程插入的时间。在那个并发哈希映射中,它将是这样的。

Key- 10
Value- 2

这意味着,2个电话在10毫秒内回来了。下面的另一个例子

Key - 20
Value -1

这意味着,1个电话在20毫秒内回来了。

该地图将包含更多数据意味着更多的键值对。

所以现在我尝试通过使用上面的相同地图来做类似下面的事情,这意味着我需要迭代上面的地图以获得该特定范围内的以下数字。这可能吗?

How many calls(X number) came back in between 1 and 20 ms
How many calls(X number) came back in between 20 and 40 ms
How many calls(X number) came back in between 40 and 60 ms
How many calls(X number) came back in between 60 and 80 ms
How many calls(X number) came back in between 80 and 100 ms
How many calls(X number) came back after 100 ms

我最初想到的一些代码。

SortedSet<Long> keys = new TreeSet<Long>(map.keySet());
for (Long key : keys) {
    System.out.print(key + " : ");
    for (int i = 0; i < map.get(key); i++) {
                 // Not sure what I am supposed to do here?
    }
    System.out.println();
}

有人可以帮我吗?

更新: -

我的地图样本值 -

{31=3, 48=1, 33=1, 30=12, 43=1, 38=1, 32=1}

通过在3+1+1+12+1+1+1 = 20

中添加value来表示总呼叫为map

除此之外,我需要弄清楚上面的情况意味着这样的事情

How many calls(X number) came back in between 1 and 20 ms
How many calls(X number) came back in between 20 and 40 ms
How many calls(X number) came back in between 40 and 60 ms
How many calls(X number) came back in between 60 and 80 ms
How many calls(X number) came back in between 80 and 100 ms
How many calls(X number) came back after 100 ms

以下是我使用以下建议尝试过的代码 -

private static void drawHistogram(Map map){

int counter[] = new int[6];

for (Integer key : map.keySet()) {
    System.out.println("" + key);    

    // add sample
    int idx = key / 20;
    idx = Math.min(idx, counter.length - 1);
    counter[idx]++;
    }

for (int i = 0; i < counter.length; i++) {
    System.out.println(counter[i] + " came back in between " + i * 20 + " and " + (i + 1) * 20
            + " ms");
}

}

如您所见,我有20个电话,但这只显示7个电话。我做错了什么?这是我得到的输出 -

0 came back in between 0 and 20 ms
5 came back in between 20 and 40 ms
2 came back in between 40 and 60 ms
0 came back in between 60 and 80 ms
0 came back in between 80 and 100 ms
0 came back in between 100 and 120 ms

仅显示7个电话。但是有20个电话。

5 个答案:

答案 0 :(得分:0)

SortedSet<Long> keys = new TreeSet<Long>(map.keySet());
Map<Long, Long> values = new HashMap<Long, Long>();
Integer total = null;
Integer current = null;
Long point = null;
for (Long key : keys) {
    System.out.print(key + " : ");
    current = map.get(key);
    if(key >= 1 && key <= 20) {
        point = 1;
    } // Do Other Comparisons also and change point 2, 3, 4, 5, 6

    total = values.get(point);
    if(total == null) {
        total = 0;
    }
    total += current;
    values.put(point, total);
    System.out.println();
}

知道您是否遍历keySet的{​​{1}}

第1点将是values

答案 1 :(得分:0)

您可以使用NavigableMap来查询一系列数字(头部,尾部)。 线程安全实现是ConcurrentSkipListMap

特别要查看方法NavigableMap<K,V> headMap(K toKey, boolean inclusive)NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)SortedMap<K,V> subMap(K fromKey, K toKey)

示例

//your existing concurrent map changed to concurrent navigable map
NavigableMap<Long, Long> throughputCounter = new ConcurrentSkipListMap<Long, Long>();
            // this prints for inclusive values - 1 and 20 are both included
            System.out.println("How many calls(X number) came back in between 1 and 20 ms:" + calcThroughput(throughputCounter.subMap(1L, true, 20L, true)));
            System.out.println("How many calls(X number) came back in between 20 and 40 ms:" + calcThroughput(throughputCounter.subMap(20L, true, 40L, true)));
            System.out.println("How many calls(X number) came back in between 40 and 60 ms:" + calcThroughput(throughputCounter.subMap(40L, true, 60L, true)));
            System.out.println("How many calls(X number) came back in between 60 and 80 ms:" + calcThroughput(throughputCounter.subMap(60L, true, 80L, true)));
            System.out.println("How many calls(X number) came back in between 80 and 100 ms:" + calcThroughput(throughputCounter.subMap(80L, true, 100L, true)));
            System.out.println("How many calls(X number) came back in after 100 ms:" + calcThroughput(throughputCounter.tailMap(100L)));

    private Long calcThroughput(NavigableMap<Long, Long> subMap) {
        Long sumOfARange = new Long(0);
        for (Long value : subMap.values()) {
            sumOfARange += value;
        }
        return sumOfARange;
    }

答案 2 :(得分:0)

根本不需要地图。您可以简单地将时间除以20(ms)并递增数组中的计数器。

public static void main( String[] args) {
    int counter[] = new int[6];
    for ( int i = 0 ; i < 100 ; i++ ) {
        int time = (int) ( Math.random() * 200 );
        System.out.println( "" + time  );
        // add sample
        int idx = time / 20;
        idx = Math.min( idx, counter.length-1);
        counter[idx]++;
    }

    for ( int i = 0 ; i < counter.length ; i++ ) {
        System.out.println( counter[i] + " came back in between " + i*20 + " and " + (i+1)*20 + " ms" );
    }
}

请注意,最后一个数组元素保存所有样本的数量&gt; = 100ms,因此应更正输出。省略尽可能简短明了的代码。

示例输出

13 came back in between 0 and 20 ms
10 came back in between 20 and 40 ms
13 came back in between 40 and 60 ms
10 came back in between 60 and 80 ms
11 came back in between 80 and 100 ms
43 came back in between 100 and 120 ms

更新:     输出应该是

for ( int i = 0 ; i < counter.length-1 ; i++ ) {
    System.out.println( counter[i] + " came back in between " + i*20 + " and " + (i+1)*20 + " ms" );
}
System.out.println( counter[counter.length-1] + " came back after 100" ms" );

答案 3 :(得分:0)

您可以尝试:

SortedSet<Long> keys = new TreeSet<Long>(map.keySet());

int group1To20=0;
int group20To40=0;
int group40To60=0;
int group60To80=0;
int group80To100=0;
int groupAbove100=0;
for (Long key : keys) {
 if(key>=0 && key<=20){
  group1To20=group1To20+map.get(key);
  }elseif(key>20 && key<=40){
   group20To40=group20To40+map.get(key);
  }
 //Similarly do as above for other range of group

}//end of loop


System.out.print("group 1-20 contains " +  group1To20);
//Now print the group range and values here

}

我已经尝试过你的解决方案了。我可能会误解你的问题。如果是这样,那么请为我澄清问题。

答案 4 :(得分:0)

预计需要轻松重新定义铲斗尺寸(实际上是你聚合的铲斗数量)我建议:

    Map<Integer, Integer> values = new HashMap<Integer, Integer>();

    int[] definition = {0, 20, 40, 60, 80, 100};
    int[] buckets = new int[definition.length];

    for (int time : values.keySet()) {
        for (int i=definition.length-1; i>=0; i--) {
            if (time >= definition[i]) {
                buckets[i] += values.get(time);
                break;
            }
        }
    }
    for (int i=0; i<definition.length; i++) {
        String period = "";
        if (i == definition.length-1) {
            period = "greater than " + definition[i] + "ms";
        } else {
            period = "between " +
                      (definition[i]+1) +
                      " and " +
                      definition[i+1] + "ms";
        }
        System.out.println(buckets[i] + " came back " + period);
    }

通过更改definition来管理可配置性。我使用以下代码来测试它:

    Random rnd = new Random();
    for (int i=0; i<1000; i++) {
        int time = rnd.nextInt(121);
        Integer calls = values.get(time);
        if (calls == null) {
            calls = Integer.valueOf(0);
        }
        calls += 1;
        values.put(time, calls);
    }