Do you know you really need to have a second index. You may find that a search of every user is fast enough, unless you have millions of users.
The following example takes 51 micro-second to scan 1,000 users. It takes 557 micro-seconds to scan 10,000 users.
I wouldn't suggest optimising the collection until your know whether it would make a difference.
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
}
}