Java HashMap indexed by 2 keys

I want to create a HashMap in java for users with settings. This would be easy to do in the database, but unfortunately I cannot use the database. I need a way to find a user by name in HashMap and find all users with a specific interest (like golf). If I delete a user, all of his interests should be deleted.

Does anyone know a good way to make this data structure?

+4
source share
8 answers

Did you know that you really need a second index. You may find that each userโ€™s search is fast enough if you donโ€™t have millions of users.

In the following example, 51 microseconds are required to scan 1000 users. Scanning 10,000 users requires 557 microseconds.

I would not suggest optimizing the collection until you know if it matters.

import java.util.*; import java.io.*; public class TestExecutor { public static void main(String[] args) throws IOException { Map<String, User> users = new LinkedHashMap<String, User>(); generateUsers(users, 1000, 0.1); // warmup. int count = 10000; for(int i=0;i< count;i++) getAllUsersWithInterest(users, Interest.Golf); long start = System.nanoTime(); for(int i=0;i< count;i++) getAllUsersWithInterest(users, Interest.Golf); long time = System.nanoTime() - start; System.out.printf("Average search time %,d micro-seconds%n", time/ count/1000); } private static Set<User> getAllUsersWithInterest(Map<String, User> users, Interest golf) { Set<User> ret = new LinkedHashSet<User>(); for (User user : users.values()) { if (user.interests.contains(golf)) ret.add(user); } return ret; } private static void generateUsers(Map<String, User> users, int count, double interestedInGolf) { Random rand = new Random(); while(users.size() < count) { String name = Long.toString(rand.nextLong(), 36); EnumSet<Interest> interests = rand.nextFloat() < interestedInGolf ? EnumSet.of(Interest.Golf) : EnumSet.noneOf(Interest.class); users.put(name, new User(name, interests)); } } static class User { private final String name; private final Set<Interest> interests; User(String name, Set<Interest> interests) { this.name = name; this.interests = interests; } } enum Interest { Golf } } 
+9
source

I would suggest you create your own data structure for storing information. Inside this class, you can have two HashMaps that store relevant information. Then write your own methods to insert and delete the user.

This way you can control the insert / delete operations by being able to request each attribute separately.

+15
source

The easiest solution is to use the Commons MultiKeyMap collection, even if it lacks generics.

... Also check out this topic genericized-commons-collection

+6
source

It seems you could use something like a bi-directional map to implement something like that. check out http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html for some doco.

although he does not give you exactly what you need in the question, his half way there.

+5
source

Just put users in ArrayList and go through it until you find the ones you need. Give each user a set of interests. Once you get enough users that take too long, sort them.

Once this takes too much time, take a look at the distribution of interests. If you have a small number of different ones, save them in a bitmap. If you have a limited set of combinations of interests, save them separately and give the user one of them.

Start simple, computers are fast. But hide the implementation so you can change it.

[hmm, getting negative votes for it]. Look at the question: you will need a lot of users before this code is as slow as a database. (on current hardware, at least a few hundred thousand)

+4
source

It may be redundant for your needs, but I donโ€™t know how complex and sensitive your needs are, so I will throw it away ...

Have you considered looking at a database (or even a local SQLite-based database) to process your data. This will allow you to store your data in such a way as to provide much greater power in the way you search / index your data, without the significant cost of creating your own code.

+4
source

I would do the following

HashMap, which includes the user as a key, and the value can be any object that includes user links. User preferences will include, for example, a list of interests.

And an additional HashMap with interest as a key and a list of users who are interested in this.

When deleting a user, you can get all interests that interest him and remove the user name from the list of interests of HashMap. When the HashMap interest list is empty, you can remove the interest from HashMap.

Use caution if 2 or more users are of the same interest. You cannot delete interest when only one user is deleted.

The disadvantage is that you will have redundant information.

+3
source

You can use 2 HashMaps. But finding only self-serving preferences can be difficult.

 HashMap <String,Hashmap> users; //save data //create new user HashMap <String,String> prefs; //save prefs prefs.put(pref1,value1); prefs.put(pref2,value2); //save user users.put(user1,prefs); //get data String x = users.get(user1).get(pref1); 

You may no longer need this solution, but many people have the same problems.

+2
source

All Articles