将字符串数组转换为Map

5

我有两个字符串数组keys和values。

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

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

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

3
Python 在这方面做得好多了 :P (https://dev59.com/7XVC5IYBdhLWcg3wsTbv) - Jason Sperske
嗯...我本来想建议使用扩展方法。但不幸的是,它只适用于C# :D - user586399
@Benedictus 哦,如果我当时能够加上“在我看来”的话就好了。为自己辩护,那是4年前的事情,当时我非常喜欢Python。我会说这仍然是我的看法,但我并不认为 OP 或其他人应该考虑更换编程语言只是为了使用数组 :) - Jason Sperske
5个回答

11

有比这更快的方法吗?

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有一些优雅的地图函数(http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#difference),但这可能是最快的方法。 - Jason Sperske
@JasonSperske:有没有OP需要的东西?我没看到。 - Bhesh Gurung
我在Guava中没有看到它,我认为ImmutableMap.of("a", 1, "b", 2, "c", 3);代码中可能有一些适用的内容,但它并不适合这个问题。你可以看看FunctionalJava中的Zipper(类似于Python的zip函数,它可以将两个列表组合成一个HashMap,但你不会获得性能优势,它只是让你以不同的方式组合这段代码)。 - Jason Sperske

4
我给您提供两种非常简单的实现方式,一种使用Java 8的Stream API,另一种则不使用。

Java < 8 (不使用Stream 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]));

2

从头开始的常数时间查找

如果您正在寻找一种可以在常数时间内检索与关键字相关联的值(即无需查看大多数值)的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);

懒惰转换,转换后常数时间查找

另一种方法是“懒惰”地进行转换,即修改上述类,使其在查找元素时仅在必要时填充内部哈希映射表:

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);
   }

}

这个解决方案意味着:
  • 立即创建您的新对象
  • 在您最初查询它的前几次中,需要线性时间查找,直到所有内容都被传输
  • 之后需要恒定时间查找,就像哈希表一样

1

在我看来,你很难找到这样的实用程序。

即使你找到了一个,它提供性能增益的可能性也非常低。因为,我认为你无法在不迭代两个数组中的所有元素的情况下完成它。

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

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

0

在Java中将两个字符串数组转换为Map

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]);
    }
 }

请查看此链接,以获取不同编程语言的更多解决方案。

注意:键应该是唯一的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接