`HlassMap`的ArrayList或`LinkedHashMap`来索引项目

时间:2013-08-12 13:50:54

标签: java collections

我需要以键值形式存储大量数据。 另外,我有两个要求

  1. 通过索引查询数据,就像从数组中查询一样。
  2. 因此,必须保留数据结构中的顺序。
  3. 对于要求2 - 我可以使用LinkedHashMap

    对于要求1 - 我有两个选择:

    • 1.1 |实现一个HashMap的ArrayList 。 [ArrayList<HashMap<String,String>>]
    • 1.2 |实现 LinkedHashMap 并使用类似的方式按索引查询项目
      • - &GT; new ArrayList(hashMapObject.entrySet()).get(0);

    问题在1.11.2中哪个更好?

    更好的是,我的意思是 - 在内存和空间方面都很有效。

    假设数据量大约是50到100个键值对,平均大小的字符串 - 比如每个键是10-30个字符,值是30-50个字符。

4 个答案:

答案 0 :(得分:3)

尝试使用SortedMap。

例如:

SortedMap<Key, Value> map = new TreeMap<Key, Value>();

这样您可以获得快速查找时间(通过密钥),但它们也保持有序。

然后你可以像这样迭代数据:

for(Key k : map.keySet()) { 
    process(map.get(k)); 
}

我最近使用它们分析了10万条推文,其中密钥是一个日期,价值是一个计数器。我想保持日期的顺序。

更新如果您只是迭代数据,那么我的方法就足够了。也许你可以提供一个小例子?如果绝对需要您也可以通过索引引用数据,那么您似乎只想维护两个数据结构,如@Jim所提到的。我以前必须这样做。

答案 1 :(得分:2)

我认为LinkedHashMap是最好的解决方案,但要获得该项目,您可以使用

hashMapObject.values().toArray()[index]

但是,toArray方法对于大量数据来说会很慢。但这是你必须要测试的东西。

如果速度确实存在问题,您可以维护HashMap 一个ArrayList。

答案 2 :(得分:2)

请记住,集合不包含对象,只有引用到对象。

使用两个集合:

  1. ArrayList用于存储索引
  2. 访问的引用
  3. 存储引用的引用HashMap
  4. 例如:

    List<MyValue> list = new ArrayList<MyValue>(100000);
    Map<MyKey,MyValue> map = new HashMap<MyKey,MyValue>(100000);
    
    while(moreItems) {
        // read input
        MyKey key = ...
        MyValue value = ...
        list.add(value);
        map.put(key,value);
    }
    
    // lookup by index
    MyValue v1 = list.get(11241);
    // lookup by key
    MyValue v2 = map.get(someKey);
    

    如果你需要交叉引用(即给定一个值对象,找到它的索引或它的键)你有一些选择:

    1. 将索引和键保存在值对象本身
    2. 将值包含在包含键和索引的“句柄”中。
    3. 例如

      class Wrapper {
          MyKey   key;
          MyValue value;
          int     index;
          // constructor, getters and setters
      }
      
      int index=0;
      while(moreItems) {
          // read input
          MyKey key = ...
          MyValue value = ...
          Wrapper w = new Wrapper(key,value,index++);
          list.add(w);
          map.put(key,w);
      }
      ...
      Wrapper w = list.get(23410);
      MyKey k = w.getKey();
      MyValue v = w.getValue();
      int i = w.getIndex();
      ...
      

答案 3 :(得分:2)

我自己去试验它。事实证明,创建 HashMaps的数组列表的方法比1000个元素快<40倍快。

public class HashMapVsArrayOfHashMap {

    public static void main(String[] args){
        ArrayList<HashMap<String, String>> listOfMaps=new ArrayList<HashMap<String,String>>();
        for( int i=0;i<1000;i++){
            final int finalI=i;
        listOfMaps.add(new HashMap<String, String>(){{put("asdfasdfasdfasdfadsf"+finalI,"asdfsdafasdfsadfasdf"+finalI);}});
        }
        LinkedHashMap<String, String> map=new LinkedHashMap<String, String>();
        for(int i=0;i<1000;i++)
            map.put("asdfasdfasdfasdfadsf"+i,"asdfsdafasdfsadfasdf"+i);     
        int position=700;
        testArrayList("Method1:ArrayListOfHashMaps",position,listOfMaps);
        testHashMap("Method2:LinkedHashMap",position,map);
    }

    private static void testArrayList(String string, int position,
            ArrayList<HashMap<String, String>> listOfMaps) {
        long start, end;
        start=System.nanoTime();
        listOfMaps.get(position).get("asdfasdfasdfasdfadsf"+position);
        end=System.nanoTime();
        System.out.println(string+"|Difference = "+(end-start));        
    }
    private static void testHashMap(String string, int position,
            LinkedHashMap<String, String> map) {
        long start, end;
        start=System.nanoTime();

        String s= new ArrayList<String>(map.keySet()).get(position);

        end=System.nanoTime();
        System.out.println(string+"|Difference = "+(end-start));        
    }
}

enter image description here

enter image description here

enter image description here

当您将尺寸增加到30,000个元素时 - 差异很大。

enter image description here

enter image description here

enter image description here