4

我想在 java 中为有偏好的用户创建一个 HashMap。这在数据库中很容易做到,但不幸的是我不能使用数据库。我需要的是一种在 HashMap 中按名称查找用户的方法,并找到所有具有特定兴趣的用户(例如高尔夫)。如果我删除一个用户,那么他们的所有兴趣都应该被删除。

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

4

8 回答 8

15

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

这样您就可以控制插入/删除操作,同时能够分别查询每个属性。

于 2009-04-28T11:20:17.040 回答
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
    }
}
于 2009-04-28T20:18:17.527 回答
6

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

...检查这个线程太genericized-commons-collection

于 2009-04-28T11:23:23.787 回答
5

似乎您可以使用双向地图之类的东西来实现这样的东西。查看http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html获取一些文档。

尽管它并不能准确地为您提供您在问题中所需要的东西,但它已经完成了一半。

于 2009-04-28T13:00:45.720 回答
4

只需将用户放在一个 ArrayList 中,然后遍历它,直到找到所需的用户。给每个用户一组兴趣。一旦你获得足够多的用户而需要很长时间,就对它们进行排序。

一旦时间太长,请看一下利益分配。如果您有少量不同的,请将它们存储在位图中。如果您的兴趣组合有限,请将它们单独存储并提供给用户其中一个。

开始简单,计算机速度很快。但是隐藏实现,所以你可以改变它。

[嗯,对此投反对票]。看看这个问题:在这段代码像数据库一样慢之前,你需要很多用户。(在目前的硬件上,至少有几十万)

于 2009-04-28T12:27:54.520 回答
4

这可能对您的需求来说有点过头了,但我不知道您的需求有多复杂和速度敏感,所以我会把它扔在那里......

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

于 2009-04-28T14:41:00.333 回答
3

我将实施以下

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

以及一个附加的 HashMap,以兴趣为键和对此感兴趣的用户列表。

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

当 2 个或更多用户有相同的兴趣时,请小心。仅删除一个用户时,您不能删除兴趣。

不利的一面是,您将拥有多余的信息。

于 2009-04-28T11:44:14.563 回答
2

您可以使用 2 个 HashMap。但只搜索低谷偏好可能会很复杂。

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

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

于 2009-09-23T07:57:25.227 回答