2011-03-13 48 views
2

我有一套需要在需要時洗牌的值。 我不知道哪種變量類型最適合我。數據實際上是基於鍵值結構的。如何洗牌鍵值對?

100 "white" 
200 "black" 
300 "red" 

等等。我想要做的是按照我還不知道的一些算法來改變鍵值對。但是他們需要像這樣改組,但洗牌需要不是隨機,所以我可以在數據恢復時我需要。

100 "red" 
200 "white" 
300 "black" 

我真的不知道我的方法應該如何解決。我應該使用HashTable還是什麼,以及如何動態地對它們進行洗牌? 任何幫助表示讚賞

+1

你所說的「混淆」是什麼意思? – marcog 2011-03-13 12:06:13

+1

如果您不知道要執行哪種算法,很難確定哪種數據結構最適合您。 – 2011-03-13 12:06:51

+0

@Max所有密鑰都是唯一的嗎? – Marnix 2011-03-13 12:07:31

回答

0

我不知道你究竟是如何去shuffle中的對,但是如果你需要基於密鑰洗牌它們,你可以使用一個Map

Map<String, String> map = new HashMap<String, String>(); 
map.put("100", "white"); 
map.put("200", "black"); 
map.put("300", "red"); 

// swap 100 with 200 
String temp = map.get("100"); 
map.put("100", map.get("200")); 
map.put("200", temp); 

或者,如果您需要隨機洗牌,您可以創建一個類Pair(其基本上將存儲intString),如larsmans所示,並將它們存儲在一個數組中。然後,可以使用Fisher-Yates shuffle的稍微修改版本。沿着這些線:

// initialize list 
List<Pair<Integer, String>> values = new ArrayList<Pair<Integer, String>>(); 
values.add(new Pair<Integer, String>(100, "white")); 
values.add(new Pair<Integer, String>(200, "black")); 
values.add(new Pair<Integer, String>(300, "red")); 

// shuffle 
System.out.println(values); // e.g., [100 white, 200 black, 300 red] 
Random random = new Random(); 
for (int i = values.size() - 1; i > 1; i--) { 
    int j = random.nextInt(i + 1); 
    // swap values between i-th Pair and j-th Pair 
    Pair<Integer, String> iPair = values.get(i); // the iPair :-) 
    Pair<Integer, String> jPair = values.get(j); 
    String iString = iPair.getSecond(); 
    iPair.setSecond(jPair.getSecond()); 
    jPair.setSecond(iString); 
} 
System.out.println(values); // e.g., [100 red, 200 black, 300 white] 
+0

或者只是對數組的形式明確。 – 2011-03-13 12:07:46

+0

感謝您response.The點是我不想ramdomly洗牌,因爲我需要的反向整理操作需要的時候。所以我需要能夠恢復它。你有什麼建議嗎? – Max 2011-03-13 17:25:52

0

它看起來像你需要一個列表的結果。地圖就是這樣。但是,像HashMap這樣的標準沒有改變鍵和值之間關係的功能。

我想我會爲此實現我自己的Map。創建一個實現java.util.Map的類,實現所需的方法並創建其他「混合」方法。

這一切都依賴於你真正需要的功能列表上的功能。你需要快速查找顏色嗎?可以有多個相同數字的tupple嗎?

+0

謝謝你的迴應。速度不是非常重要的問題。而對於你的第二個問題,不。 – Max 2011-03-13 12:22:11

4

另一種方式爲隨機洗牌鍵 - 值映射:

public static <K,V> void shuffleMap(Map<K,V> map) { 
    List<V> valueList = new ArrayList<V>(map.values()); 
    Collections.shuffle(valueList); 
    Iterator<V> valueIt = valueList.iterator(); 
    for(Map.Entry<K,V> e : map.entrySet()) { 
     e.setValue(valueIt.next()); 
    } 
} 

編輯:

如果你不想改變原有的地圖(因爲你需要它以後),您可以創建,而不是一個新問題:

public static <K,V> Map<K,V> shuffleMap(Map<K,V> map) { 
    List<V> valueList = new ArrayList<V>(map.values()); 
    Collections.shuffle(valueList); 
    Iterator<V> valueIt = valueList.iterator(); 
    Map<K,V> newMap = new HashMap<K,V>(map.size()); 
    for(K key : map.keySet()) { 
     newMap.put(key, valueIt.next()); 
    } 
    return newMap; 
} 

你真的不希望一個seemingl y隨機混合,這可以恢復(這很快變得複雜),但只保留你的原始地圖。如果這不合適,你需要更好地描述你的問題。


好的,你想通過使用密鑰加密映射,給出另一個映射,然後再解密它。很顯然隨機洗牌在這裏沒有什麼幫助,甚至僞隨機也不好,因爲它沒有提供可靠的重新洗牌方式。在基本情況下,您的密鑰將是映射關鍵字之間的可逆映射。

public static <K,V> Map<K,V> encryptMap(Map<K,V> plainMap, Map<K,K> key) { 
    Map<K,V> cryptoMap = new HashMap<K,V>(plainMap.size()); 
    for(Map.Entry<K,V> entry : plainMap.entrySet()) { 
     cryptoMap.put(key.get(entry.getKey()), entry.getValue()); 
    } 
    return cryptoMap; 
} 

解密的作用相同,實際上只使用密鑰的反向映射。

所以,當你有你的{100, 200, 300}例如按鍵,這些按鍵中的任意排列是我們的「加密方案」有效的關鍵。 (只有6個可能的,這是不是很安全。)

Map sampleKey = new HashMap<Integer, Integer>(); 
sampleKey.put(100, 200); 
sampleKey.put(200, 300); 
sampleKey.put(300, 100); 

Map sampleUnKey = new HashMap<Integer, Integer>(); 
for(Map.Entry<Integer, Integer> e : sampleKey) { 
    sampleUnKey.put(e.getValue(), e.getKey()); 
} 

Map<Integer, String> data = new HashMap<Integer, String>(); 
data.put(100, "white"); 
data.put(200, "black"); 
data.put(300, "red"); 

System.out.println(data); 

Map<Integer, String> encrypted = encryptMap(data, sampleKey); 

System.out.println(encrypted); 

Map<Integer, String> decrypted = encryptMap(data, sampleUnKey); 

System.out.println(decrypted); 

地圖decrypted現在應該是一樣的原始地圖。

對於更大的按鍵組,你會想找到一個方案,從某些輸入能夠拿到鑰匙合適 排列鍵。

+0

感謝您的回覆。關鍵是我不想隨意洗牌,因爲在需要時我需要反向洗牌操作。所以我需要能夠恢復它。你有什麼建議嗎? – Max 2011-03-13 17:26:43

+0

顯然,從你的問題來看,你並不清楚你真正想要什麼,即使是這個例子。簡單地創建一個新的洗牌地圖(並保留舊地圖)就夠了嗎?如果不是,請更清楚地描述您的要求。 – 2011-03-13 18:02:02

+0

我需要保留從混洗地圖中的舊(原始)地圖。認爲這就像加密/解密。現在更清楚了嗎? – Max 2011-03-13 18:12:41