Sergio76
Sergio76

Reputation: 3986

Make several "for loops" with different parameters in a single execution

In my application I have a for loop that gets data from a map and adds it to a new map that will contain more data from other data sources (several enumClass). I do it this way:

private static Map<String, String> myMapConversion() {

        for (myEnunClassKeyOne key : document.keySet()) {

            String keyObteined = key.toString();
            String value = document.get(key);

            globalConfig.put(convertKey(keyToConversion), value); // Extension function get value of myEnunClassKeyOne key
        }

        return globalConfig;
    }

I have to do the same with other enumClasses and add the data to the same globalConfig map, something like this:

private static Map<String, String> mapConversion() {

        for (myEnunClassKeyONE key : document.keySet()) {

            String keyObteined = key.toString();
            String value = document.get(key);

            globalConfig.put(convertKey(keyToConversion), value); // Extension function get value of myEnunClassKeyOne key
        }

        for (myEnunClassKeyTWO key : document.keySet()) {

            String keyObteined = key.toString();
            String value = document.get(key);

            globalConfig.put(convertKey(keyToConversion), value); // Extension function get value of myEnunClassKeyOne key
        }

        for (myEnunClassKeyTHREE key : document.keySet()) {

            String keyObteined = key.toString();
            String value = document.get(key);

            globalConfig.put(convertKey(keyToConversion), value); // Extension function get value of myEnunClassKeyOne key
        }

        return globalConfig;
    }

Repeating the for loops seems "inelegant" to me. Can you think of a way to do this in a more automated way?

I've tried a few ways, but haven't been able to get it to work. It would have to be java code, although a Kotlin extension function can be accepted

Thanks in advance

--- Edited based on answers ---

@Tenfour04 you are very kind.

My problem is that the type of document1, document2, etc is not validated and I don't know how to type it correctly. I include more details:

enum class Document1(val currentKey: String) {

    color1("blue"),
    color1("red"),
    color1("green"),
    color1("cyan"),
    color1("yellow"),
    color_show("yes"),
    ...
}

enum class Document2(val currentKey: String) {

    word1("hello"),
    word1("sky"),
    word1("orange"),
    word1("smile"),
    word1("beauty"),
    word_show("yes"),
    ...
}

For this reason, when I include Document1, Document2, etc. in "map documents", I get a required type error

   ...
        Map<?, ?>[] documents = { Document1, Document2, Document3** };
    ...

Upvotes: 0

Views: 59

Answers (1)

Tenfour04
Tenfour04

Reputation: 93551

In Java, you can create a list of your items and iterate that. I'm assuming these are actually three different documents.

private static Map<String, String> mapConversion() {
    List<Map<?, String>> documents = List.of(document1, document2, document3);
    for (Map<?, String> document : documents) {
        for (Map.Entry<?, String> entry : document.entrySet()) {
            String key = entry.getKey().toString();
            String value = entry.getValue();
            globalConfig.put(convertKey(keyToConversion), value);
        }
    }
    return globalConfig;
}

In Kotlin, you can do this a little more concisely using mapKeysTo:

fun mapConversion(): MutableMap<String, String> {
    listOf(document1, document2, document3).forEach { 
        it.mapKeysTo(globalConifg) { (key, _) -> convertKey(key.toString()) }
    }
    return globalConfig
}

Sorry, I missed the Android tag. Pre-Java 9 you can use an array but I think you have to cast the returned values:

private static Map<String, String> mapConversion() {
    Map<?, ?>[] documents = { document1, document2, document3 };
    for (Map<?, ?> document : documents) {
        for (Map.Entry<?, String> entry : document.entrySet()) {
            String key = entry.getKey().toString();
            String value = (String)entry.getValue();
            globalConfig.put(convertKey(keyToConversion), value);
        }
    }
    return globalConfig;
}

Since they are enum definitions and not maps, you need a way to generically treat them the same. One way is to add a way to get a map from each of them. Like this in each Enum:

enum class Document1(val currentKey: String) {

    color1("blue"),
    color1("red");

    companion object {
        @JvmStatic val valuesMap: Map<String, Document1>() =
            values().associateBy(Document1::currentKey)
    }
}

Then you can use the maps:

Map<?, ?>[] documents = { Document1.getValuesMap(), Document2.getValuesMap(), Document3.getValuesMap() };

In this case, the map values are the various enum types, so you'll maybe have to convert them to Strings with toString() to put them in your global map.

Upvotes: 2

Related Questions