Java: How to use a pair of keys for HashMap
From a sql database, I am reading a tabl开发者_StackOverflow中文版e with 2 fields: appName, user. So I may see:
+-------------+
| appA | John |
+-------------+
| appB | Mary |
+-------------+
| appC | Tom |
+-------------+
| appA | John |
+-------------+
| appA | Mary |
+-------------+
Each of these records is stored as an object of a AppClass with appName and user. Now, i want to list how many times the apps were run by different users. So :
+-----------------+
| appA | John | 2 |
+-----------------+
| appA | Mary | 1 |
+-----------------+
| appB | Mary | 1 |
+-----------------+
| appC | Tom | 1 |
+-----------------+
Is it possible do the counting with a HashMap with 2 keys?
Yes it is possible, create an AppUser
class that includes the appName and the user. Override hashCode()
and equals()
for your AppUser
class.
You can then use a:
Map<AppUser, Integer> map;
Yes. Create a pair that implements hashCode()
and equals()
properly and use that as the key type. If you're using a library like apache commons you can probably find a pair or tuple class there, but otherwise the below will work.
Don't overdo generic pairs though. It's fine to define a key class to handle the relationship between a pair of items in a collection, but many people have principled objections to wide use of pair classes in Java.
public final class PairKey<A, B> {
public final A a;
public final B b;
private PairKey(A a, B b) { this.a = a; this.b = b; }
public static <A, B> PairKey<A, B> make(A a, B b) { return new PairKey<A, B>(a, b); }
public int hashCode() {
return (a != null ? a.hashCode() : 0) + 31 * (b != null ? b.hashCode() : 0);
}
public boolean equals(Object o) {
if (o == null || o.getClass() != this.getClass()) { return false; }
PairKey that = (PairKey) o;
return (a == null ? that.a == null : a.equals(that.a))
&& (b == null ? that.b == null : b.equals(that.b));
}
}
and then to put an entry for a and b into the map, just do
myMap.put(new PairKey(a, b), value)
how about
Map<String, Integer> appUserToCountMap
use appA:John
as key for example
Yes, you can have a structure like the following:
Map<String, Map<String, Integer>>
^ ^ ^
appName user count
But it'd be much easier if you just fetch the aggregated data directly from the database:
SELECT appName, user, COUNT(*)
FROM table
GROUP BY appName, user;
You can also consider using Commons Collections' Bag. See Bag.getCount(key)
精彩评论