3

I have this following method:

public static <T, U> T[] getKeysForValue(Map<T,U> map,U value){
    if(map == null || map.isEmpty()) {
        return null;
    }

    Set<T> keys = new HashSet<T>();

    for (Map.Entry<T,U> entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            keys.add(entry.getKey());
        }
    }

    return keys.toArray(new T[keys.size()]);
}

I am getting compilation error on the line: keys.toArray(new T[keys.size()]), which says "Cannot create a generic array of T", which is obvious. How can I solve this issue?

4
  • 6
    @feralin A longer, actually useful answer would be better. Some of the apparent deficiencies in Java's generics system can be made to work by using explicit type tokens. Unfortunately those don't help when the type parameter is itself parameterised, but that's not the case here. Not knowing how to do this in Java isn't a good excuse for trolling. Commented Jul 11, 2013 at 14:08
  • @feralin I have equal expertise in C# and Java, so it would be very much controversial to compare them. Commented Jul 11, 2013 at 14:11
  • @millimoose why do you say I'm trolling? Would you please provide some proof or evidence of that? Commented Jul 11, 2013 at 14:49
  • 2
    @feralin Your comment is at the very least a close neighbor to "the answer is your language sucks". Seeing as intent doesn't transfer over the internet I have no "proof" of it, but then again we're not in a court of law. Also, splitting hairs over this is ignoring the crux of my objection, which is that your comment wasn't very constructive. Commented Jul 11, 2013 at 16:04

2 Answers 2

5

Why not just return the Set? That seems to make more sense in this context anyway.

public static <T, U> Set<T> getKeysForValue(Map<T, U> map, U value) {
    ...

    return keys;
}

An alternative, if you still want to return an array, would be to pass an array to be filled as an argument:

public static <T, U> T[] getKeysForValue(Map<T,U> map, U value, T[] dest) {
    ...

    return keys.toArray(dest);
}
Sign up to request clarification or add additional context in comments.

Comments

4

You should pass the class corresponding to T as argument of your method and call Array.newInstance(clazz, size)

public static <T, U> T[] getKeysForValue(Class<T> clazz, Map<T,U> map,U value){

  T[] array = (T[])Array.newInstance(clazz, size);

5 Comments

Without passing clazz there is no way? By determining the class type of the key at runtime, can't I do that?
No, because of type erasure in generics, the type is not known at runtime so you have no chance to guess it. At runtime, Map<T,U> basically becomes Map<Object, Object>.
+1, There is other way, I did my own answer. I should have tried little more before. :-)
Might want an @SuppressWarnings("unchecked")
not gonna work if the caller doesn't have the class of T either (T is a type variable in caller). we cannot pass the class through all APIs. the better answer is - don't use array, use collection.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.