Java HashMap 以 2 个键为索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/797367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:50:52  来源:igfitidea点击:

Java HashMap indexed on 2 keys

javadata-structuresmaphashmap

提问by Marius

I want to create a HashMap in java for users with preferences. This would be easy to do in a database, but unfortunately I can't use a database. What I need is a way to find a user by name in the HashMap, and to find all the users with a certain interest (e.g. golf). If I delete a user, then all their interests should be deleted.

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

Anyone know a nice way to make this data structure?

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

回答by B.E.

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

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

This way you have control over the insert/delete-operations while being able to query each attribute separately.

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

回答by Peter Lawrey

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.

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

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

回答by KarlP

Simplest solution is to use a Commons Collection MultiKeyMapeven if it is lacking generics.

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

...Check this thread too genericized-commons-collection

...检查这个线程太泛化-commons-collection

回答by Chii

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

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

although it doesnt give you exactly what you need in the question, its half the way there.

虽然它没有给你你在问题中所需要的东西,但它已经完成了一半。

回答by RHSeeger

This may be overkill for your needs, but I don't know how complex and speed sensitive your needs are, so I'll throw it out there...

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

Have you considered looking at an in-memory (or even local disk based like SQLite) database to handle your data. Doing so would allow you to store your data in a way that allows much more power in how you search/index your data, without many of the costs of writing your own code.

您是否考虑过查看内存(或什至基于本地磁盘,如 SQLite)数据库来处理您的数据。这样做将使您能够以一种更强大的方式存储数据,从而在搜索/索引数据方面具有更大的能力,而无需承担编写自己的代码的许多成本。

回答by Stephan Eggermont

Just put the users in an ArrayList, and walk over it till you found the one(s) you need. Give each user a set of interests. Once you get enough users that it takes too long, sort them.

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

Once that takes too long, take a look at the distribution of interests. If you have a low number of different ones, store them in a bitmap. If you have a limited set of combinations of interests, store them separately and give a user one of these.

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

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

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

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

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

回答by Markus Lausberg

I would implement the following

我会实施以下

HashMap which include the user as key and the value could be any object which includs the userpreferences. The user preferences would include a list of interest for example.

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

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

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

When you delet a user, you can get all the interest he has and delete the user name from the interest HashMap list. When the interest HashMap list is empty you can delet the interest from the HashMap.

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

Take care, when 2 or more users have the same interest. You can not delet the interest when only one user is deleted.

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

The downside is, that you will have redundant informations.

缺点是,您将拥有冗余信息。

回答by Konstantin Petrukhnov

You could use 2 HashMaps. But searching only trough preferences could be complicated.

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

Maybe you don't need this solution anymore, but many people still have same problems.

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