views:

305

answers:

6

I need to store key/value info in some type of collection. In C#, I'd define a dictionary like this:

var entries = new Dictionary<string, int>();
entries.Add("Stop me", 11);
entries.Add("Feed me", 12);
entries.Add("Walk me", 13);

Then I would access the values so:

int value = entries["Stop me"];

How do I do this in Java? I've seen examples with ArrayList, but I'd like the solution with generics, if possible.

+2  A: 

It looks like you are looking for something like HashMap

yx
+22  A: 

You want to use a Map

Map<String, Integer> m = new HashMap<String, Integer>();
m.put("Stop me", 11);
Integer i = m.get("Stop me"); // i == 11

Note that on the last line, I could have said:

int i = m.get("Stop me");

Which is shorthand for (with Java's auto-unboxing):

int i = m.get("Stop me").intValue()

If there is no value in the map at the given key, the get returns null and this expression throws a NullPointerException. Hence it's always a good idea to use the boxed type Integer in this case

oxbow_lakes
+1  A: 

You definitely want a HashMap, which is the Java version of C# Dictionary.

McWafflestix
+6  A: 

You use a Map in Java.

Note that you can't use int (or any other primitive type) as a generic type parameter, but because of autoboxing, it still behaves almost as if it were a Map<String, int> instead of a Map<String, Integer>. (You don't want to be doing a lot of autoboxing in performance-sensitive code, though.)

Map<String, Integer> entries = new HashMap<String, Integer>();
entries.put("Stop me", 11);
entries.put("Feed me", 12);
entries.put("Walk me", 13);
int value = entries.get("Stop me"); // if you know it exists
// If you're not sure whether the map contains a value, it's better to do:
Integer boxedValue = entries.get("Punch me");
if (boxedValue != null) {
    int unboxedValue = boxedValue;
    ...
}
Michael Myers
Your last line is dangerous: if there is no value in the map at that key, it will throw a NullPointerException because of your use of unboxing
oxbow_lakes
Yes, good point. Autoboxing is very nice, but unboxing doesn't really help that much.
Michael Myers
Roll on the @NotNull annotation
oxbow_lakes
+7  A: 

Use a java.util.Map. There are several implementations:

  • HashMap: O(1) lookup, does not maintain order of keys
  • TreeMap: O(log n) lookup, maintains order of keys, so you can iterate over them in a guaranteed order
  • LinkedHashMap: O(1) lookup, iterates over keys in the order they were added to the map.

You use them like:

Map<String,Integer> map = new HashMap<String,Integer>();
map.put("Stop me", 11);
map.put("Feed me", 12);

int value = map.get("Stop me");

For added convenience working with collections, have a look at the Google Collections library. It's excellent.

Nat
Repeat comment: Your last line is dangerous: if there is no value in the map at that key, it will throw a NullPointerException because of your use of unboxing
oxbow_lakes
+1 for explaination about Map implementations
dfa
There is a value in the map with that key! But to clarify, you would first check for a missing key by calling the map's contains method and/or checking that the result of get(key) is not null. The latter is less likely, since it is poor practice to pass mulls between objects.
Nat
Oops. I mean "nulls" not "mulls".
Nat
It would have deserved a +1 for Map explanation if the O's were correct. HashMap and LinkedHashMap provide constant-time - O(1) - performance, not O(n). Their worst-case performance (i.e. all objects have same hash) is O(n)
oxbow_lakes
I realised I'd mistyped them and found you'd just beat me to the correction!
Nat
+1  A: 
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Stop Me", 11);
map.put("Feed Me", 12);
map.put("Walk Me", 13);
Integer x; // little hack
int value = (x = a.get("aaa")) == null? 0 : x;

as alternative you can try Enum:

enum Action {

    STOP(11),
    FEED(12),
    WALK(13);

    private final int value;

    private Action(int value) {
        this.value = value;
    }

    public int value() {
        return value;
    }

    public static Action valueOf(int value) {
        for (Action action : values()) {
            if (action.value == value) {
                return action;
            }
        }

        return null; // or a null-object
    }
}

test:

public void action() {
    Action action = Action.valueOf("FEED"); 
    // or Action.FEED for more compile-time safety
    int value = action.value();
    // instantiating by code 
    Action walk = Action.valueOf(13);
}
dfa
Repeat Comment: Your last line is dangerous: if there is no value in the map at that key, it will throw a NullPointerException because of your use of unboxing
oxbow_lakes
good point, using a boxed type should be better
dfa
Let's hope the user has names that are legal java identifiers.
kd304
Having an Enum where null is somehow a value, isn't really an enum. A enum is supposed to enumerate the possible values
oxbow_lakes