【问题标题】:String[] or ArrayList better as Key in HashMap?String[] 或 ArrayList 更好地作为 HashMap 中的键?
【发布时间】:2015-07-10 01:32:33
【问题描述】:

所以我需要在两者之间做出选择

  1. HashMap<String[], Object>
  2. HashMap<ArrayList<String>,Object>

我的输入参数是:ArrayList<String> in

整个ArrayList<String> in 不能是键,因为它确实包含元素,这些元素不应该像数据库中的主键。我知道,传入的ArrayList<String> in 的第一个n 元素应该是主键

哪个会更快?

场景:

HashMap<ArrayList<String>, Object> hmAL = new HashMap<>();
HashMap<String[], Object> hmSA = new HashMap<>();
ArrayList<String> in = new ArrayList<>(); 
fillWithStuff(in);

//Which one would be faster?
getObject(in,hmAL,5);
getObject(in,hmSA,5);

使用选项 1:

private Object getObject(ArrayList<String> in, HashMap<ArrayList<String>, Object> hm, int n){
  return hm.get(in.sublist(0,n));
}

使用选项 2:

private Object getObject(ArrayList<String> in, HashMap<String[], Object> hm, int n){
String[] temp = new String[n];
for(int i=0; i<n; i++)
  temp[i]=in.get(i);

  return hm.get(temp);
}

考虑:

  1. 哪个更快?缩短列表,还是复制到数组?
  2. 我想知道,哪个哈希(因为它是一个 HashMap)会更快。 ArrayList 或大小相等的数组的散列。还是没有任何区别?

【问题讨论】:

  • HashMap 中使用容器作为键可能不是一个好主意。
  • 为什么不是个好主意?
  • 因为插入密钥后容器的内容可能会发生变化,而Java没有const对象。
  • 您可能会发现有用的 Guava Multimap
  • @Fede:有类似逆番石榴多重映射的东西吗?比如:一个值有多个键?

标签: java arrays string performance arraylist


【解决方案1】:

使用String[] 不是一个好主意,因为它没有实现hashCode()。这意味着如果您有 2 个字符串数组,它们是不同的对象但具有完全相同的值,则地图将找不到它。

“hashCode”的实现似乎使用了每个字符串元素的哈希码,因此在地图中的查找会成功。所以我会选择这个。

也就是说,我宁愿自己根据列表中的对象构建一个密钥。

【讨论】:

    【解决方案2】:

    仅处理复制

    subList 方法在 Java 7+ 中非常有效地实现,根本不需要任何复制。它只是将视图直接返回到原始数组上。因此,在 Java 7+ 中,它将比逐元素复制方法更快。但是,在 Java 6 中,这两种方式本质上是等价的。

    整体处理方法

    如果您查看整个方法,您的选择不再是选择。如果您希望该方法起作用,则必须使用第一个实现。数组hashCode() 不查看其中的元素——只查看数组的标识。因为您是在方法中创建数组,所以Map.get() 必须返回null

    另一方面,List.hashCode() 方法对所有包含的元素运行哈希,这意味着如果所有包含的元素都相同,它将成功匹配。

    您的选择很明确。

    【讨论】:

      【解决方案3】:

      只是为了补充以上两个答案,我已经在 J​​ava 7 中进行了测试,发现平均而言,使用 2000000 总元素和 1000000 参与计算 hashcode 的元素(即主键)的 list 速度快 50 倍(假设数)。下面是程序。

      public class TestHashing {
      
          public static void main(String[] args) {
              HashMap<ArrayList<String>, Object> hmAL = new HashMap();
              HashMap<String[], Object> hmSA = new HashMap<>();
              ArrayList<String> in = new ArrayList<>();
              fillWithStuff(in);
      
              // Which one would be faster?
              long start = System.nanoTime();
              getObject(in, hmAL, 1000000);
              long end = System.nanoTime();
      
              long firstTime = (end-start);
              System.out.println("firstTime :: "+ firstTime);
      
              start = System.nanoTime();
              getObject1(in, hmSA, 1000000);
              end = System.nanoTime();
      
              long secondTime = (end-start);
      
              System.out.println("secondTime :: "+ secondTime);
      
             System.out.println("First is faster by "+ secondTime/firstTime);
          }
      
          private static void fillWithStuff(ArrayList<String> in) {
              for(int i =0; i< 2000000; i++) {
                  in.add(i+"");
              }
          }
      
          private static Object getObject(ArrayList<String> in,
                  HashMap<ArrayList<String>, Object> hm, int n) {
              return hm.get(in.subList(0, n));
          }
      
          private static Object getObject1(ArrayList<String> in, HashMap<String[], Object> hm, int n){
              String[] temp = new String[n];
              for(int i=0; i<n; i++)
                temp[i]=in.get(i);
      
                return hm.get(temp);
              }
      }
      

      输出

      firstTime :: 218000
      secondTime :: 11627000
      First is faster by 53
      

      【讨论】:

        猜你喜欢
        • 2012-04-15
        • 1970-01-01
        • 1970-01-01
        • 2014-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        • 1970-01-01
        相关资源
        最近更新 更多