4

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.

Anyone know a nice way to make this data structure?

4

8 に答える 8

15

情報を保持するための独自のデータ構造を作成することをお勧めします。そのクラス内には、関連情報を格納する 2 つの HashMap を含めることができます。次に、ユーザーを挿入および削除する独自のメソッドを記述します。

このようにして、各属性を個別に照会しながら、挿入/削除操作を制御できます。

于 2009-04-28T11:20:17.040 に答える
9

2 番目のインデックスが本当に必要であることをご存知ですか。何百万ものユーザーがいない限り、すべてのユーザーの検索が十分に高速であることがわかる場合があります。

次の例では、1,000 人のユーザーをスキャンするのに 51 マイクロ秒かかります。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

最も簡単な解決策は、ジェネリックスがない場合でもCommonsCollectionMultiKeyMapを使用することです。

...このスレッドがあまりにも一般化されていることを確認してください-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

これはあなたのニーズにはやり過ぎかもしれませんが、あなたのニーズがどれほど複雑でスピードに敏感かはわかりません。

データを処理するためにインメモリ (または SQLite のようなローカル ディスク ベース) データベースを検討したことがありますか。そうすることで、独自のコードを書くための多くのコストをかけずに、データを検索/インデックス化する方法を大幅に強化できる方法でデータを保存できます。

于 2009-04-28T14:41:00.333 に答える
4

ユーザーを ArrayList に入れ、必要なユーザーが見つかるまでそれを調べてください。各ユーザーに一連の興味を与えます。時間がかかりすぎるほど十分な数のユーザーを獲得したら、それらを並べ替えます。

時間がかかりすぎたら、関心の分布を見てみましょう。異なるものの数が少ない場合は、それらをビットマップに保存します。興味の組み合わせが限られている場合は、それらを個別に保存し、ユーザーにその 1 つを提供します。

簡単に始めましょう。コンピューターは高速です。ただし、実装を非表示にして、変更できるようにします。

[うーん、これには反対票が集まっています]。質問を見てください。このコードがデータベースと同じくらい遅くなる前に、多くのユーザーが必要になります。(現在のハードウェアでは、少なくとも数十万)

于 2009-04-28T12:27:54.520 に答える
3

私は以下を実装します

ユーザーをキーとして含む HashMap と値は、ユーザー設定を含む任意のオブジェクトにすることができます。ユーザー設定には、たとえば、関心のあるリストが含まれます。

そして、関心をキーとする追加の HashMap と、これに関心のあるユーザーのリスト。

ユーザーを削除すると、そのユーザーの関心をすべて取得し、関心 HashMap リストからユーザー名を削除できます。対象の HashMap リストが空の場合、HashMap から対象を削除できます。

2 人以上のユーザーが同じ興味を持っている場合は注意してください。ユーザーが 1 人だけ削除されている場合、関心を削除することはできません。

欠点は、冗長な情報が得られることです。

于 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 に答える