HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Map<K, Object> => Map<K, String>

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mapstringobject

Problem

Given a Map, I'm returning Map or throwing an Exception for at least one non-String value.

private static  Map validate(final Map map) 
                        throws NonStringValueException {
    final List invalidValues = new ArrayList();
    final Map result = new HashMap();

    for(Map.Entry entry : map.entrySet()) {
        if(!(entry.getValue() instanceof String)) {
            invalidValues.add(entry.getValue());
        }
        else {
            result.put(entry.getKey(), (String) entry.getValue());
        }
    }

    if(!invalidValues.isEmpty()) {
        throw new NonStringValueException("Invalid Values: 
            must be `String` type: " + invalidValues);
    }

    return result;
}


Besides using instanceOf and then casting, is there a better way to write this method?

Solution

Some simple things first - there's no need to repeat the generic type of variables on the right-hand-side of a new assignment. Java 7 introduced the "diamond operator" <> and the generic type is inferred. So, lines like:

final List invalidValues = new ArrayList();
final Map result = new HashMap();


can be just:

final List invalidValues = new ArrayList<>();
final Map result = new HashMap<>();


Your use of the static method and generic type ` is good. I like how you have made the variables final in the method too. Additionally, your use of the for-each loop on the Map's entries is also good.

A comment on your generics, your input map should be
Map instead of Map .... the ? allows more flexibility.

Java introduced a couple of helper methods on
Class` a while back, and I think you could use these to make this method even more generic.... why force it to only be a String?

Consider the following two methods:

private static  Map validate(Class coerce, final Map map) 
        throws IllegalArgumentException {
    final List invalidValues = new ArrayList<>();
    final Map result = new HashMap<>();

    for(Map.Entry entry : map.entrySet()) {
        if(coerce.isInstance(entry.getValue())) {
            result.put(entry.getKey(), coerce.cast(entry.getValue()));
        } else {
            invalidValues.add(entry.getValue());
        }
    }

    if(!invalidValues.isEmpty()) {
        throw new IllegalArgumentException("Invalid Values: must be `" + coerce.getName() +  "` type: " + invalidValues);
    }

    return result;
}

public static  Map validate(Map map) {
    return validate(String.class, map);
}

Code Snippets

final List<Object> invalidValues = new ArrayList<Object>();
final Map<K, String> result = new HashMap<K, String>();
final List<Object> invalidValues = new ArrayList<>();
final Map<K, String> result = new HashMap<>();
private static <K, V> Map<K, V> validate(Class<V> coerce, final Map<K, ?> map) 
        throws IllegalArgumentException {
    final List<Object> invalidValues = new ArrayList<>();
    final Map<K, V> result = new HashMap<>();

    for(Map.Entry<K, ?> entry : map.entrySet()) {
        if(coerce.isInstance(entry.getValue())) {
            result.put(entry.getKey(), coerce.cast(entry.getValue()));
        } else {
            invalidValues.add(entry.getValue());
        }
    }

    if(!invalidValues.isEmpty()) {
        throw new IllegalArgumentException("Invalid Values: must be `" + coerce.getName() +  "` type: " + invalidValues);
    }

    return result;
}

public static <K> Map<K, String> validate(Map<K, ?> map) {
    return validate(String.class, map);
}

Context

StackExchange Code Review Q#96905, answer score: 4

Revisions (0)

No revisions yet.