排序的地图实现(ValueComparableMap),在调用Map.Entry setValue时不进行排序

时间:2015-07-08 11:05:00

标签: java dictionary guava treemap

我使用过解决方案here,它描述了如何在java中实现一个可比值的地图,并且它对put方法工作正常,但是,当我尝试修改地图中已有的值时Map.Entry类型,不再维护排序。以下代码展示了问题:

TreeMap<Integer, Float> valCompMap = new ValueComparableMap<Integer, Float>(Ordering.natural());
// some code that puts entries in map
Random random = new Random();
for (Map.Entry<Integer, Float> e : valCompMap.entrySet()) {
  e.setValue(e.getValue() + random.nextFloat());
}
//parse keys into list
List<Integer> sorted_keys = new ArrayList<Integer>(valCompMap.keySet()); //here sorted_keys are not sorted according to values in original key value pair in the map

作为一种解决方法,我将重新放置具有新值的键:

List<Integer> keys = new ArrayList<Integer>(valCompMap.keySet());
for (Integer k : keys) {
  valCompMap.put(k, valCompMap.get(k) + random.nextFloat());
}

解决问题:

  1. 不直接(没有明确表达意图)
  2. 因为查看put中的ValueComparableMap方法,它似乎效率不高,它涉及分支,搜索,删除和2x推送。
  3. 那么在ValueComparableMap中修改值的有效方法是什么(在保持实时排序属性的同时)?

    这是一个简单的测试来证明问题:

    TreeMap<Integer, Float> valCompMap = new ValueComparableMap<Integer, Float>(Ordering.natural());
    
    //populate map with random stuff
    Random random = new Random();
    for (int i = 0; i < 10; ++i) {
      valCompMap.put(i, random.nextFloat());
    }
    
    //print
    System.out.println("Before modifying, map:");
    for (Map.Entry<Integer, Float> e : valCompMap.entrySet()) {
      System.out.println(e.toString());
    }
    
    //modify values in map
    for (Map.Entry<Integer, Float> e : valCompMap.entrySet()) {
      e.setValue(e.getValue() + random.nextFloat());
    }
    
    //print
    System.out.println("After modifying, map:");
    for (Map.Entry<Integer, Float> e : valCompMap.entrySet()) {
      System.out.println(e.toString());
    }
    
    //modify values in work-around way
    List<Integer> keys = new ArrayList<Integer>(valCompMap.keySet());
    for (Integer k : keys) {
      valCompMap.put(k, valCompMap.get(k) + random.nextFloat());
    }
    
    //print
    System.out.println("After modifying using work-around, map:");
    for (Map.Entry<Integer, Float> e : valCompMap.entrySet()) {
      System.out.println(e.toString());
    }
    

    这是输出:

    Before modifying, map:
    6=0.05478877
    4=0.07464349
    1=0.08668131
    2=0.0869472
    3=0.32622492
    8=0.35595274
    5=0.3879655
    9=0.602066
    7=0.7913183
    0=0.8479772
    
    After medifying, map:
    6=0.9277618
    4=0.9426463
    1=0.269701
    2=0.95250356
    3=0.8576952
    8=0.547724
    5=1.1656129
    9=1.3945209
    7=1.0475534
    0=0.91609937
    
    After modifying using work-around, map:
    3=0.96215
    6=1.036502
    4=1.1082084
    1=1.1496286
    8=1.2940607
    7=1.343531
    0=1.4778173
    2=1.6039091
    5=1.6165544
    9=2.1403322
    

0 个答案:

没有答案