我有一组值需要在需要时进行洗牌。 我不知道哪种变量类型最适合我。数据实际上是基于键值结构。喜欢;
100 "white"
200 "black"
300 "red"
并且喜欢那样。我想要做的是根据我还不知道改变键值对,一些算法。但是他们需要像这样改组,但改组需要不是随机,所以我可以在需要时恢复数据。
100 "red"
200 "white"
300 "black"
我真的不知道我的方法应该如何解决。我应该使用HashTable还是其他东西,我该如何动态地对它们进行洗牌? 任何帮助表示赞赏
答案 0 :(得分: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;
}
你真的不希望看似随机混合,可以恢复(这很快变得复杂),但只是保留原始地图。如果这不合适,您需要更好地描述您的问题。
好的,您希望使用密钥加密映射,给出另一个映射,然后再次解密。显然随机改组在这里没有用,甚至伪随机也没有用,因为它没有提供可靠的重新洗牌方式。在基本情况下,您的密钥将是我们映射的密钥之间的可逆映射。
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
现在应该与原始地图相同。
对于更大的键集,您可能希望找到一个合适的方案 从一些可输入密钥中置换密钥。
答案 1 :(得分: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
(基本上会存储int
和String
),如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]
答案 2 :(得分:0)
看起来你需要一个tupples列表。地图就是这样。但是,像HashMap这样的标准没有改变键和值之间关系的功能。
我想我会为此实现自己的Map。创建一个实现java.util.Map的类,实现所需的方法并创建一些“混合”的其他方法。
这一切都取决于你在tupples列表中真正需要的功能。你需要快速查找颜色吗?可以有不止一个具有相同数字的tupple?