Java HashMap索引在2个键上

时间:2009-04-28 11:14:40

标签: java data-structures map hashmap

我想在java中为具有首选项的用户创建一个HashMap。这在数据库中很容易做到,但不幸的是我无法使用数据库。我需要的是一种在HashMap中按名称查找用户并找到具有特定兴趣的所有用户(例如高尔夫球)的方法。如果删除用户,则应删除所有兴趣。

任何人都知道制作这种数据结构的好方法吗?

8 个答案:

答案 0 :(得分:15)

我建议您创建自己的数据结构来保存信息。在该类中,您可以使用两个HashMaps存储相关信息。然后编写自己的方法来插入和删除用户。

通过这种方式,您可以控制插入/删除操作,同时可以单独查询每个属性。

答案 1 :(得分:9)

你知道你真的需要第二个索引吗?您可能会发现每个用户的搜索速度都很快,除非您有数百万用户。

以下示例需要51微秒才能扫描1,000个用户。扫描10,000个用户需要557微秒。

我不建议优化收藏品,直到你知道它是否会有所作为。

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
    }
}

答案 2 :(得分:6)

最简单的解决方案是使用Commons Collection MultiKeyMap,即使它缺少泛型。

...也检查此帖子genericized-commons-collection

答案 3 :(得分:5)

似乎你可以使用像双向地图这样的东西来实现这样的东西。查看http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html了解一些doco。

虽然它不能完全满足你在问题中的需要,但却只有它的一半。

答案 4 :(得分:4)

只需将用户放在ArrayList中,然后遍历它直到找到所需的用户。为每个用户提供一组兴趣。一旦获得足够多的用户需要花费太长时间,请对其进行排序。

一旦花费太长时间,请查看兴趣分布。如果您的数量不同,请将它们存储在位图中。如果您有一组有限的兴趣组合,请单独存储它们并为用户提供其中一种。

开始简单,电脑很快。但隐藏实现,以便您可以更改它。

[嗯,得到负面投票]。看看这个问题:在此代码与数据库一样慢之前,您需要大量用户。 (在当前的硬件上,至少有几十万)

答案 5 :(得分:4)

这对你的需求可能有点过分,但我不知道你的需求有多复杂和速度敏感,所以我会把它扔出去......

您是否考虑过查看内存(甚至是基于SQLite的本地磁盘)数据库来处理数据。这样做可以让您以一种方式存储数据,从而在搜索/索引数据方面拥有更强大的功能,而无需编写自己的代码。

答案 6 :(得分:3)

我会实现以下

包含用户作为键的HashMap,值可以是包含用户首选项的任何对象。例如,用户首选项将包括感兴趣的列表。

另外一个感兴趣的HashMap和一个对此感兴趣的用户列表。

当您删除用户时,您可以获得他所有的兴趣并从感兴趣的HashMap列表中删除用户名。 当兴趣HashMap列表为空时,您可以从HashMap中删除兴趣。

当2个或更多用户具有相同兴趣时,请小心。当只删除一个用户时,您无法删除兴趣。

缺点是,你将有多余的信息。

答案 7 :(得分:2)

您可以使用2个HashMaps。但只搜索低谷优惠可能很复杂。

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);

也许你不再需要这个解决方案,但很多人仍然有同样的问题。