【问题标题】:Java HashMap indexed on 2 keys在 2 个键上索引的 Java HashMap
【发布时间】:2009-04-28 11:14:39
【问题描述】:

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

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

【问题讨论】:

  • 您的主题具有误导性,正如您在一些答案中看到的那样。

标签: java data-structures map hashmap


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    以下示例需要 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
        }
    }
    

    【讨论】:

      【解决方案3】:

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

      ...也检查一下这个帖子genericized-commons-collection

      【讨论】:

        【解决方案4】:

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

        虽然它并没有准确地为您提供问题所需的内容,但它已经完成了一半。

        【讨论】:

          【解决方案5】:

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

          您是否考虑过使用内存(甚至是本地磁盘,例如 SQLite)数据库来处理您的数据。这样做可以让您以一种更强大的方式来存储您的数据,以便您搜索/索引您的数据,而无需编写自己的代码。

          【讨论】:

            【解决方案6】:

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

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

            开始简单,计算机速度很快。但隐藏实现,以便您可以更改它。

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

            【讨论】:

              【解决方案7】:

              我会执行以下操作

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

              还有一个额外的 HashMap,以兴趣为键,以及对此感兴趣的用户列表。

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

              请注意,当 2 个或更多用户有相同的兴趣时。只删除一个用户时,不能删除兴趣。

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

              【讨论】:

                【解决方案8】:

                您可以使用 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);
                

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

                【讨论】:

                  猜你喜欢
                  • 2011-02-10
                  • 2020-05-29
                  • 2021-12-03
                  • 2011-10-30
                  • 1970-01-01
                  • 2011-04-27
                  • 2012-05-30
                  • 2021-03-12
                  • 1970-01-01
                  相关资源
                  最近更新 更多