【问题标题】:Converting string arrays into Map将字符串数组转换为 Map
【发布时间】:2012-09-14 04:52:44
【问题描述】:

我有两个字符串数组键和值

String[] keys = {a,b,c,d};

String[] values = {1,2,3,4};

将它们转换为地图的最快方法是什么?我知道我们可以遍历它们。但是,是否有任何实用程序存在?

【问题讨论】:

  • Python 在这方面要好得多:P (stackoverflow.com/questions/209840/…)
  • 嗯...我想建议扩展方法。但不幸的是,它仅在 C# 中:D
  • @Benedictus 哦,我只能添加“在我看来”,在我的辩护中,那是 4 年前,我相当爱上了 Python。我会说这仍然是我的观点,但我并不是说 OP 或其他任何人都应该考虑切换语言来处理数组:)

标签: java arrays hashmap


【解决方案1】:

比这还快?

Map<String,String> map = new HashMap<>();

if(keys.length == values.length){
    for(int index = 0; index < keys.length; index++){
        map.put(keys[index], values[index]);
    }
}

【讨论】:

  • Google Guava 有一些优雅的地图功能 (code.google.com/p/guava-libraries/wiki/…) 但这可能是最快的方法。
  • @JasonSperske:有什么 OP 正在寻找的吗?我没有看到。
  • 我在 Guava 中看不到它,尽管 ImmutableMap.of("a", 1, "b", 2, "c", 3);可能适用的代码,但它不适合该问题。你可能会看一下 FunctionalJava 中的 Zipper(就像 Python 的 zip 函数,它可以将两个列表组合成一个 HashMap,但你没有获得性能优势,它只是让你以不同的方式编写这段代码)
【解决方案2】:

我打算给你两个非常简单的实现。一个带有 Java 8 的流 Api,一个没有。

Java (无流 api)

if(keys.length != values.length) { 
    throw new IllegalArgumentException("Keys and Values need to have the same length."); 
}
Map<String,String> map = new HashMap<>();
for (int i = 0; i < keys.length; i++) {
    map.put(keys[i], values[i]);
}

Java > 8 (带有流 api)

if(keys.length != values.length) { 
    throw new IllegalArgumentException("Keys and Values need to have the same length."); 
}
Map<String,String> map = IntStream.range(0, keys.length).boxed()
    .collect(Collectors.toMap(i -> keys[i], i -> values[i]));

【讨论】:

    【解决方案3】:

    从头开始的恒定时间查找

    如果您正在寻找一个在恒定时间内检索与键关联的值的 Map(这意味着不必查看大多数值),那么您将无法做得更快,因为需要处理数组。

    但是,您可以使用已经以这种方式编写的实用程序:com.google.common.collect.Maps.uniqueIndex

    瞬时转换,线性时间查找

    如果您对每次都在数组中搜索键的 Map 感到满意,那么您可以通过定义一个实现 Map 接口的新类来立即使用您的两个数组创建 Map:

    class TwoArrayMap implements Map<String, String> {
    
       private final String[] keys;
       private final String[] values;
       // If you want to enable to add more key value pairs to your map, and
       // want to make the process faster, you could use ArrayLists instead of arrays
    
       public TwoArrayMap(String[] array1, String[] array2){
           if(array1 == null || array2 == null || array2.length < array1.length)
              throw new IllegalArgumentException();
           keys = array1;
           values = array2;
           // Alternatively, you could want to clone the arrays, to 
           // make sure they are not modified, using array1.clone(), etc
       }
    
       public String get(String key){
    
           for(int i=0; i<keys.length; i++)
                 if(key == null && key == null || key != null && key.equals(k) )
                    return values[i];
           return null;                     
       }
    
       public String put(String key, String Value) throws OperationNotSupportedException {
            throw new OperationNotSupportedException();
            // alternatively, you could resize the arrays and add a new key, or use an ArrayList
       }
    
    }
    
    Map<String, String> myMap = new TwoArrayMap(keys, values);
    


    惰性转换,转换后恒定时间查找

    另一种方法是“懒惰”地进行,即修改上述类,使其在内部保留对 HashMap 的引用,并仅在查找元素时填充它:

    class TwoArrayMap implements Map<String, String> {
    
       private final Map<String, String> hashmap;
       private int maxIndexAlreadyTransferred = -1;
    
       private final String[] keys;
       private final String[] values;
    
       public TwoArrayMap(String[] array1, String[] array2){
           if(array1 == null || array2 == null || array2.length < array1.length)
              throw new IllegalArgumentException();
           hashmap = new HashMap<>();
           keys = array1;
           values = array2;
           // Alternatively, you could want to clone the arrays, to 
           // make sure they are not modified, using array1.clone(), etc
       }
    
       public String get(String key){
    
           if(hashmap.containsKey(key))
                return hashmap.get(key);
    
           String k, value;
           while( maxIndexAlreadyTransferred + 1 < keys.length ){
                 k = keys[ maxIndexAlreadyTransferred + 1 ];
                 value = values[ maxIndexAlreadyTransferred +1 ];
                 if(!hashmap.containsKey(k))
                     hashmap.put( k, value );
                 maxIndexAlreadyTransferred++;
                 if(key == null && k == null || key != null && key.equals(k) )
                    return value;
           }
           return null;                     
       }
    
       public String put(String key, String Value) {
            hashmap.put(key, value);
       }
    
    }
    

    这个解决方案意味着:

    • 即时创建新对象
    • 第一次查询时的线性时间查找,直到所有内容都传输完毕
    • 之后的恒定时间查找,表现为哈希表

    【讨论】:

      【解决方案4】:

      恕我直言,您不太可能找到这样的实用程序。

      但是,即使您发现它提供任何性能提升的机会非常低。因为,我认为如果不遍历两个数组中的所有元素,您将无法做到这一点。

      我可以建议的一件事是(仅当您的数组具有大量元素时)您可以在实例化地图时指定地图的容量,以减少在将条目放入其中时调整大小的开销。

      Map<String, String> map = new HashMap<String, String>(keys.length);
      //put keys and values into map ...
      

      【讨论】:

        【解决方案5】:

        Convert two String arrays to Map in Java

        import java.util.HashMap;
         public static void main(String[] args){
            String[] keys= {"a", "b", "c"};
            int[] vals= {1, 2, 3};
            HashMap<String, Integer> hash= new HashMap<String, Integer>();
        
            for(int i= 0; i < keys.length; i++){
              hash.put(keys[i], vals[i]);
            }
         }
        

        查看LINK 了解更多不同编程语言的解决方案

        Note : 键应该是唯一的..

        【讨论】:

          猜你喜欢
          • 2014-07-08
          • 1970-01-01
          • 2017-11-27
          • 2011-06-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多