2011-03-13 91 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