Makis Papapanagiotou
Makis Papapanagiotou

Reputation: 67

iterate over this generic SET with wildcards

I cannot find a way to iterator over the SET below using wildcards. I have also tried to convert it like it is mentioned in Effective Java but still get compilation error.

public void testWildCardIteration() {

    LinkedHashMap<String, ?> result = new LinkedHashMap<>();
    Set<Map.Entry<String, ?>> entrySet = // entries....

    iterHelper(entrySet, result);

}

private <E> void iterHelper(Set<Map.Entry<String, E>> entrySet , LinkedHashMap<String, E> result) {
    for (Map.Entry<String, E> entry : entrySet) {
        String tmpkey = entry.getKey();

        if (tmpkey.startsWith("KEY")) {
            result.put(entry.getKey(), entry.getValue());
        }
    }
}

Upvotes: 1

Views: 280

Answers (2)

gil.fernandes
gil.fernandes

Reputation: 14611

You can use wildcards in the read only collection. But you will have to use a super lower bounded wildcard applied to the collection to which you are writing.

In essence this should compile:

public void testWildCardIteration() {

    LinkedHashMap<String, ? super Object> result = new LinkedHashMap<>(); // write collection 
    Set<Map.Entry<String, ?>> entrySet = new HashSet<>(); // read collection

    iterHelper(entrySet, result);

}

private void iterHelper(Set<Map.Entry<String, ?>> entrySet, LinkedHashMap<String, ? super Object> result) {
    for (Map.Entry<String, ?> entry : entrySet) {
        String tmpkey = entry.getKey();

        if (tmpkey.startsWith("KEY")) {
            result.put(entry.getKey(), entry.getValue());
        }
    }
}

Here is a simple test which shows the code working:

public static void testWildCardIteration() {

    LinkedHashMap<String, ? super Object> result = new LinkedHashMap<>();
    Set<Map.Entry<String, ?>> entrySet = new HashSet<>();

    entrySet.add(new AbstractMap.SimpleEntry<String, Object>("KEY", "BLAH"));
    iterHelper(entrySet, result);

    System.out.println(result);
}

private static void iterHelper(Set<Map.Entry<String, ?>> entrySet, LinkedHashMap<String, ? super Object> result) {
    for (Map.Entry<String, ?> entry : entrySet) {
        String tmpkey = entry.getKey();

        if (tmpkey.startsWith("KEY")) {
            result.put(entry.getKey(), entry.getValue());
        }
    }
}

public static void main(String[] args) {

    testWildCardIteration();
}

This prints out:

{KEY=BLAH}

Upvotes: 1

davidxxx
davidxxx

Reputation: 131346

The E method scoped is not required.
As it doesn't specify any bound, it uses Object by default.

Instead, specify ? as type of Entry.value of entrySet and specify Object as type of Entry.value of result.
Note that you cannot specify ? as type such as Set<?> as you want to add not nulls in a collection. But with Object such as Set<Object> you can do it.

private  void iterHelper(Set<Map.Entry<String, ?>> entrySet , LinkedHashMap<String, Object> result) {
    for (Map.Entry<String, ?> entry : entrySet) {
        String tmpkey = entry.getKey();

        if (tmpkey.startsWith("KEY")) {
            result.put(entry.getKey(), entry.getValue());
        }
    }
}

You can now invoke it :

LinkedHashMap<String, Object> result = new LinkedHashMap<>();
Set<Map.Entry<String, ?>> entrySet = ...;
iterHelper(entrySet, result);

Upvotes: 1

Related Questions