2013-01-31 70 views
7

我想知道是否有可能将HashMap拆分为更小的子地图。如何在Java中拆分HashMap

在我的情况下,我有一个HashMap的100个元素,我想从原始创建2个(或更多)较小的HashMap,第一个包含从0到49的条目,第二个包含从50到99.

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

//should contains entries from 0 to 49 of 'bigMap' 
Map <Integer, Integer> smallMap1 = new HashMap <Integer, Integer>(); 


//should contains entries from 50 to 99 of 'bigMap' 
Map <Integer, Integer> smallMap2 = new HashMap <Integer, Integer>(); 

有什么建议吗?非常感谢!

回答

12

您是否必须使用HashMap

TreeMap对这种事情真的很好。这是一个例子。

TreeMap<Integer, Integer> sorted = new TreeMap<Integer, Integer>(bigMap); 

SortedMap<Integer, Integer> zeroToFortyNine = sorted.subMap(0, 50); 
SortedMap<Integer, Integer> fiftyToNinetyNine = sorted.subMap(50, 100); 
+0

谢谢我会尝试 – RNO

+2

downvoter护理评论为什么这不是一个好的答案? – sharakan

+0

我不知道为什么你收到了一些downvote,我选择了你的答案,因为它不会浪费太多的记忆。 TreeMap使我能够高效地实现我想要的。附:我应该指出,结果应该是表现出来的,而你的建议就是这样。再次感谢 – RNO

3

您基本上需要迭代bigMap中的条目,并决定是将它们添加到smallMap1还是smallMap2

+0

或设定阈值,重复它,移动从大到小每一个条目迭代 – amphibient

+0

@ foampile:阈值?你什么意思? (记住散列图未被排序) –

+0

迭代达到一定数量的迭代,例如, 50%四舍五入到原始大小的下一个整数。但即使没有排序,他也会移动条目,即将它们放入新的,从旧的删除,因此它是安全的。所以当他再次迭代时,旧的 – amphibient

0
for (Map.Entry<Integer,Integer> entry : bigMap.entrySet()) { 
    // ... 
} 

是迭代原始地图的最快方式。然后,您可以使用Map.Entry键来决定填充哪张新地图。

3

由于HashMap是无序的(条目可能以任何顺序出现),因此完全拆分它是没有意义的。我们可以简单地使用交替布尔标志。

boolean b = false; 
for (Map.Entry e: bigMap.entrySet()) { 
    if (b) 
    smallMap1.put(e.getKey(), e.getValue()); 
    else 
    smallMap2.put(e.getKey(), e.getValue()); 
    b = !b; 
} 
+2

呵呵?在HashMap上不会随便选择其他所有条目吗? – sharakan

+0

HashMap中没有条目的顺序。如果顺序对您的任务很重要,请使用LinkedHashMap,然后它当然必须是不同的算法。 – h22

+0

如果我不考虑排序,它只是我想将地图分割成更小的地图。我该怎么做 ? – vkrishna17

1

遍历bigMapfor (Entry<Integer, Integer> entry : bigMap.entrySet()),并增加了i检查是否必须添加在第一小地图,或在第二个条目。

1

这里是一个SortedMap的解决方案:

public static <K, V> List<SortedMap<K, V>> splitMap(final SortedMap<K, V> map, final int size) { 
    List<K> keys = new ArrayList<>(map.keySet()); 
    List<SortedMap<K, V>> parts = new ArrayList<>(); 
    final int listSize = map.size(); 
    for (int i = 0; i < listSize; i += size) { 
     if (i + size < listSize) { 
      parts.add(map.subMap(keys.get(i), keys.get(i + size))); 
     } else { 
      parts.add(map.tailMap(keys.get(i))); 
     } 
    } 
    return parts; 
} 
+0

这绝对是一个完美的答案.. – Chinni

0

这是其中做的工作我的功能之一,我希望它为别人有帮助的。无论存储为键的对象/原语如何,这个都可以工作。

树形图的方式提出上述仅如果键元,有序,在指数的精确序列将工作..

public List<Map<Integer, EnrichmentRecord>> splitMap(Map<Integer, EnrichmentRecord> enrichmentFieldsMap, 
      int splitSize) { 

     float mapSize = enrichmentFieldsMap.size(); 
     float splitFactorF = splitSize; 
     float actualNoOfBatches = (mapSize/splitFactorF); 
     double noOfBatches = Math.ceil(actualNoOfBatches); 



     List<Map<Integer, EnrichmentRecord>> listOfMaps = new ArrayList<>(); 

     List<List<Integer>> listOfListOfKeys = new ArrayList<>(); 


     int startIndex = 0; 
     int endIndex = splitSize; 

     Set<Integer> keys = enrichmentFieldsMap.keySet(); 
     List<Integer> keysAsList = new ArrayList<>(); 
     keysAsList.addAll(keys); 

     /* 
     * Split the keys as a list of keys, 
     * For each key sub list add to a Primary List - listOfListOfKeys 
     */ 
     for (int i = 0; i < noOfBatches; i++) { 
      listOfListOfKeys.add(keysAsList.subList(startIndex, endIndex));   
      startIndex = endIndex; 
      endIndex = (int) (((endIndex + splitSize) > mapSize) ? mapSize : (endIndex + splitSize)); 
     } 

     /** 
     * For Each list of keys, prepare a map 
     * 
     **/ 
     for(List<Integer> keyList: listOfListOfKeys){ 
      Map<Integer,EnrichmentRecord> subMap = new HashMap<>(); 
      for(Integer key: keyList){ 
       subMap.put(key,enrichmentFieldsMap.get(key)); 
      } 
      listOfMaps.add(subMap); 
     } 

     return listOfMaps; 
    }