views:

173

answers:

3

I am having some trouble creating a for loop within a constructor to iterate over a map and an array at the same time. Here, it is indicated that this cannot be done with an enhanced for loop.

I have something like this, which raises a compiler error. Basically, the class has a Map which I want to populate via the constructor which takes a collection and a variable number of integers as parameters.

The var-arg expression evaluates to an array of integers, so I tried to put both enhanced iterators in the same loop, but didn't work.

private final Map<Module, Integer> modules = new HashMap<Module, Integer>();    
    AssemblyType(Collection<Module> modules, int... units) {
     int i = 0;
     for (Module module : modules, int i : units) {
      this.modules.put(module, units[i]);
     }  
    }

Thanks for any ideas on how to proceed.

+2  A: 

The naive way to do this would just be to track i yourself:

private final Map modules = new HashMap();    
    AssemblyType(Collection modules, int... units) {
        int i = 0;
        for (Module module : modules) {
                this.modules.put(ingredient, units[i]);
                i++;
        }               
    }

I'm not sure if there's a better way, but I'm pretty sure you can't combine two iterators inside a single for loop like your original example.

Tim
The simplest way is usually the best. It also works in this case because the var args are the same length as the collection! Thanks
denchr
A: 

It looks like your trying to pass a the modules Map as a Collection which would cause a compile error.

Code to iterate over both could be something like this

public MyMethod(Map<Object, Object> objectMap, Integer ... intArray) {
    if( intArray.length != ObjectMap.size() ) {
       //However you want to handle this case
    }
    Iterator<Object> mapKeyIterator = objectMap.keySet().iterator();
    Iterator<Integer> integerIterator = Arrays.asList(intArray).iterator();

    while(mapKeyIterator.hasNext()) { //If the array and map are the same size then you only need to check for one.  Otherwise you'll need to validate both iterators have a next
        Object keyFromMap = mapKeyIterator.next();
        Object valueFromMap = objectMap.get(keyFromMap);
        Integer intFromArray = integerIterator.next();
        //Whatever you want to do
   }
}

If you know they are the same length then you could also traverse the array with a for(int i ... loop and just use an iterator for the map if you didn't want to create a List.

Patrick Auld
A: 

This seems like a very error-prone API, to ask for a completely disconnected map and array. Not just error-prone, but it will be hard for readers of the code to be able to tell which int goes with which map entry. I always advise against this kind of API. Try a Map<Object, MySpecialType> where MySpecialType aggregates both an Object and an int.

Kevin Bourrillion
Yes, it might be a bit risky. Would you mind giving a short example on the approach you are suggesting
denchr
it's hard when the problem is stated in such vague terms; if you could make it more concrete it would help. (note: my answer here is slightly easier to understand now that I went back and escaped the angle brackets properly -- aughghghg.)
Kevin Bourrillion