5

I have two string arrays keys and values

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

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

What is the fastest way to convert them into a map? I know we can iterate through them. But, is there any utility present?

3
  • 3
    Python is so much better at this :P (stackoverflow.com/questions/209840/…) Commented Sep 14, 2012 at 5:01
  • Hmmm... I would liked suggesting extension methods. But unfortuntaley, it is in C# only :D Commented Sep 14, 2012 at 5:16
  • @Benedictus oh that I could I could have only added "in my opinion", in my defense it was 4 years ago and I was rather in love with Python. I will say that it is still my opinion but I don't seriously mean that the OP or anyone else should consider switching languages just to work with arrays :) Commented Nov 11, 2016 at 12:14

5 Answers 5

11

Faster than this?

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]);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Google Guava has some elegant functions for maps (code.google.com/p/guava-libraries/wiki/…) but this is probably the fastest method.
@JasonSperske: Is there what OP is looking for? I don't see one.
I don't see it in Guava, I though there was something to the ImmutableMap.of("a", 1, "b", 2, "c", 3); code that might apply, but it's not a fit for the problem. You might look at Zipper in FunctionalJava (like Python's zip function which can combine two lists into a HashMap, but you don't get a performance advantage, it just lets you compose this code in a different way)
4

I purpose to you two very simple implementations. One with stream Api of Java 8, one without.

Java < 8 (without 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 (with stream 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]));

Comments

2

Constant time lookup from the start

If you are looking for a Map that retrieves the value associated with a key in constant time (meaning without having to look at most values), then you cannot do much faster, because the arrays need to be processed.

However, you can use a utility already written that way : com.google.common.collect.Maps.uniqueIndex

Instantaneous conversion, Linear time lookup

If you are ok with a Map that searches the array for the key every time, then you can create the Map instantly using your two arrays, by defining a new class that implements the Map interface :

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


Lazy conversion, constant time lookup after conversion

Another approach would be to do it "lazily", meaning modify the above class, so that it keeps a reference to a HashMap internally, and fills it only when it is looking up elements :

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

}

This solution would mean :

  • an instantaneous creation of your new object
  • linear time lookup for the first times you will query it, until everything is transferred
  • constant time lookup after that, behaving as a hash table

Comments

1

IMHO, it's highly unlikely that you will find a utility like that.

But, even if you find one chances are really low that it will provide any performance gain. Because, I think you won't able to do it without iterate through all the elements in both the arrays.

One thing I can suggest is (only if your arrays have a huge number of elements) that you can specify the capacity of the map while instantiating it to reduce overhead of resizing while you put entries into it.

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

Comments

0

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

Check this LINK for more solutions in different programming languages

Note : The keys should be unique..

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.