簡體   English   中英

Java HashMap索引在2個鍵上

[英]Java HashMap indexed on 2 keys

我想在java中為具有首選項的用戶創建一個HashMap。 這在數據庫中很容易做到,但不幸的是我無法使用數據庫。 我需要的是一種在HashMap中按名稱查找用戶的方法,以及查找具有特定興趣的所有用戶(例如高爾夫)。 如果刪除用戶,則應刪除所有興趣。

任何人都知道制作這種數據結構的好方法嗎?

我建議你創建自己的數據結構來保存信息。 在該類中,您可以使用兩個HashMaps存儲相關信息。 然后編寫自己的方法來插入和刪除用戶。

這樣,您可以控制插入/刪除操作,同時可以單獨查詢每個屬性。

你知道你真的需要第二個索引嗎? 除非您擁有數百萬用戶,否則您可能會發現對每個用戶的搜索速度都很快。

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

最簡單的解決方案是使用Commons Collection MultiKeyMap,即使它缺少泛型。

...檢查此線程太genericized-commons-collection

看起來你可以使用像雙向地圖這樣的東西來實現這樣的東西。 查看http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html了解一些doco。

雖然它不能完全滿足你在問題中所需要的東西,但卻只有它的一半。

只需將用戶放在ArrayList中,然后遍歷它直到找到所需的用戶。 為每個用戶提供一組興趣。 一旦獲得足夠多的用戶需要花費太長時間,請對其進行排序。

一旦花費太長時間,請查看興趣分布。 如果您的數量不同,請將它們存儲在位圖中。 如果您有一組有限的興趣組合,請單獨存儲它們並為用戶提供其中一種。

開始簡單,電腦很快。 但隱藏實現,以便您可以更改它。

[嗯,得到負面投票]。 看看這個問題:在此代碼與數據庫一樣慢之前,您需要大量用戶。 (在目前的硬件上,至少有幾十萬)

這對你的需求可能有點過分,但我不知道你的需求有多復雜和速度敏感,所以我會把它扔出去......

您是否考慮過查看內存(甚至是基於SQLite的本地磁盤)數據庫來處理數據。 這樣做可以讓您以一種方式存儲數據,從而在搜索/索引數據方面擁有更強大的功能,而無需編寫自己的代碼。

我會實現以下內容

包含用戶作為鍵的值的HashMap和值可以是包含用戶首選項的任何對象。 例如,用戶偏好將包括感興趣的列表。

另外還有一個感興趣的HashMap和一個對此感興趣的用戶列表。

當您刪除用戶時,您可以獲得他所有的興趣並從感興趣的HashMap列表中刪除用戶名。 當興趣HashMap列表為空時,您可以從HashMap中刪除興趣。

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

也許你不再需要這個解決方案,但很多人仍然有同樣的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM