简体   繁体   中英

java hashmap keys

Is there any reason why you would use anything other than String as a hashmap key? It seems like Strings are good enough 99% of the time. Plus, you don't have to implement hashCode() and equals(Object o). Thanks

Imagine a case where you want to create a map keyed off a user's type and name. In that case you would be best to write a class composed of 2 fields (and overriding hashCode and equals ). Using a single String in this case, and trying to somehow compose these 2 pieces of information down into a single String would be very awkward and bug prone.

Like Mark Elliot said, sometimes there is a natural key which doesn't have a natural String form. Why not use it?

Strings are good enough when you have a String form handy or one is obvious, such as when you're dealing with database entities.

However, performance is another reason.

Of course, if you do implement a custom key you must ABSOLUTELY ensure it is immutable. it's not only a preference, as trashgod says. Also, Comparable is pretty irrelevant.

If you have a mutable key in a hash map, you can break your hashmap completely.

Sometimes you want an object instead of a string

Suppose that you have a map of... lets say a map (dictionary, or other hashtables) of customers and restaurant orders.

Instead of having

Customer c = new Customer("Bob");
Order o = new Order("Fries");
HashMap<string, Order> map = new HashMap<string, Order>();
map.put(c.Name, o);

You could access everything with a Customer object with

Hashmap<Customer, Order> map = new HashMap<Customer, Order>();
map.put(c, o);

Now why would you prefer this?

Maybe in your restaurant, you have multiple Customers called "Bob" on that particular night, so just having a HashMap of names isn't enough anymore. Your Customer class will reflect the differences between the "Bob"s, but just a string representing each of them will not do.

By having a HashMap of Customers, you can simply change the Customer class hashing algorithm and everything will work perfectly (hopefully). If you had proceeded with strings, it would not be as easy to make modifications and uniquely identify each object instance

Strings can cover a lot of use cases, but using more complicated objects can give you a lot more flexibility in your code. Seeing that in the US they've just announced the NCAA college basketball tournament seeds, I'll see if I can come up with a tournament-themed example.

Suppose I want to build a Hashmap that stores all of the teams that are in each region. There are four regions to the tournament: East, West, Southwest, and Southeast. You could certainly create your map as:

HashMap<String, List<Team>> teamsInRegions = new HashMap<String, List<Team>>();

But then, what if you already have an object that represents a region? You likely would, since each region has a lot more information associated with it than a name. For instance, I figure a Region class might look like:

public class Region {
    private String name;

    private Calendar firstRound;
    private String firstRoundLocation;

    private Calendar secondRound;
    private String secondRoundLocation;

    private Calendar thirdRound;
    private String thirdRoundLocation;

    ....
}

You get the idea. If the HashMap were keyed by a String, you could certainly get away with having a reasonable Region.toString() method and using that as the key, but using the more complex object will allow you to write more flexible code.

While others may disagree, I find myself using Maps in somewhat unpredictable ways sometimes, where calling HashMap.keySet() gives me a Set of fully populated, complex objects with a plethora of information. And having the Map there means I can use those objects to make decisions elsewhere as well.

For instance, suppose I wanted to build up a list of all the locations of all the games in the basketball tournament. If I had my HashMap with complex objects, that would be as simple as:

Set<Region> regions = myMap.keyset();
Set<String> gameLocations = new HashSet();
for (Region region : regions) {
    gameLocations.add(region.getAllLocales());
}

And so on. YMMV.

Advantages:
1) String's immutable => Thread Safe , no concurrency issues
2) String's hashcode is cached (look for private int hash in JDK for String class). Saves a lot of processing time.
3) String pool for literals(reuse of string objects) or intern strings created using new operator to add them into pool
4) Security, no one can edit a key
5) Equals and hashcode is implemented well

Downside:
1) String pool poses a security risk of exposing password in clear text to anyone who has access to memory of java application. Core dump of java application, generating memory dump in /tmp can put passwords in real threat.
Solution : For passwords use char[] you can erase convents by setting it blank or any other character which reduces security risk of exposing password.

Strings are probably the most common use case but it really depends on what you want to store. You would not want to turn a Long into String just to keep your key a String. Just use the type as your data structures suggest. For types like eg Long you don't have to implement hashCode/equals either. If you are thinking about custom classes implementing equals and hashCode might be a good idea anyway. Implementing it with eg Apache Commons' EqualBuilder it's also pretty straight forward.

I suppose that you could say that String is "good enough" because you can turn typical key types into Strings. However, doing this could well be expensive relative to the cost of using the real key type as the hash table key. Consider for example, converting an Integer (or int ) to a String each time you want to use it as a hash table key ...

The other point is that implementing hashCode and equals on a key type is dead-easy. So easy in fact that IDEs like Eclipse have the ability to generate these two methods for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM