我想在形式Map
:创建Java中的地图是需要的地图整数随机
0 -> 1
2 -> 0
1 -> 2
或者
0 -> 4
1 -> 0
2 -> 2
3 -> 3
4 -> 1
每INT应该准确地映射到不同的INT在范围中。 我想通过功能的int
地图的大小,并取回一个Map
对象。 实现此功能的好方法是什么?
我想在形式Map
:创建Java中的地图是需要的地图整数随机
0 -> 1
2 -> 0
1 -> 2
或者
0 -> 4
1 -> 0
2 -> 2
3 -> 3
4 -> 1
每INT应该准确地映射到不同的INT在范围中。 我想通过功能的int
地图的大小,并取回一个Map
对象。 实现此功能的好方法是什么?
public static Map<Integer,Integer> bijectiveMap(int n) {
List<Integer> values = new ArrayList<>(n);
for (int i=0 ; i<n ; i++)
values.add(i);
Collections.shuffle(values);
Map<Integer,Integer> result = new HashMap<>();
for (int i=0 ; i<n ; i++)
result.put(i,values.get(i));
return result;
}
输出对于n = 10:
{0=7, 1=5, 2=3, 3=6, 4=1, 5=4, 6=2, 7=8, 8=9, 9=0}
洗牌可能会做。可能不是最快的,但肯定是最干净的方式。
public Map<Integer, Integer> getRandomMapping(int min, int max){
List<Integer> arr = new ArrayList<Integer>();
//Fill array in order
for(int i = 0; i < max + 1; i++){
arr.add(i + min);
}
//Shuffle
Collections.shuffle(arr);
//Read into map
Map<Integer, Integer> m = new HashMap<Integer, Integer>();
for(int i = 0; i < max + 1; i++){
m.put(new Integer(i + min), arr.get(i));
}
return m;
}
忘记Map
。只是洗牌的Array
/ArrayList
(与a[i] = i
初始化)。分配质量取决于您的洗牌算法。
+1,数组/ ArrayList更容易使用。如果由于某种原因确实需要返回一个'Map',你可以创建一个包装数组并实现'Map'接口的类。 – 2014-08-31 15:40:19
如果避免Collections.shuffle。这里
public static Map<Integer, Integer> foo(final int size) {
final Map<Integer, Integer> out = new HashMap<Integer, Integer>(size*5);
final List<Integer> values = new ArrayList<Integer>(size);
Random r = new Random();
for (int i = 0; i < size; i++) {
values.add(i, i);
}
for (int i = size; i > 0; i--) {
out.put(new Integer(i), values.remove(r.nextInt(i)));
}
return out;
}
为int和长期使用Apache的集合,而不是整数包装器
final static transient Random r = new Random();
final public static Map<Integer, Integer> foo(final int size) {
final Map<Integer, Integer> out = new HashMap<Integer, Integer>(size*5);
final List<Integer> values = new ArrayList<Integer>(size);
int i;
for (i = 0; i < size; i++) {
values.add(i, i);
}
for (; i > 0; i--) {
out.put(new Integer(i), values.remove(r.nextInt(i)));
}
return out;
}
我的列表道歉循环,这是太多的std ::今天载体。快速的解决方案
final static transient Random rand = new Random();
final public static Map<Integer, Integer> foo(final int size) {
final Map<Integer, Integer> out = new HashMap<Integer, Integer>(size*5);
final Integer[] values = new Integer[size];
int i, r;
for (i = 0; i <size; i++) {
values[i] = i;
}
for (; i > 0; i--) {
r = rand.nextInt(i);
out.put(i, values[r]);
values[r] = values[i-1];
}
return out;
}
Your implementation,size = 100_000:1557 ms,size = 1_000_000:167130 ms。使用Collections.shuffle实现,size = 100_000:95 ms,size = 1_000_000:2934 ms。你说得快多快?除去'values'的元素有一个可怕的代价,而Collections.shuffle只交换元素。无论如何! – Dici 2014-08-31 16:54:49
问题解决了,我不想开始辩论。我想说的是删除一个ArrayList的元素是O(n),所以你最后一个循环是O(n^2),而Collections.shuffle是O(n)。期。自己试试! http://pastebin.com/Se7CugK4 – Dici 2014-08-31 17:50:42
是的,我同意.... – 2014-08-31 17:55:12
使数组0..N,然后洗牌,然后把地图从0到N的顺序。好吧,如果大小从一开始就知道。 – 2014-08-31 15:04:57
'实现这个功能的最有效的方法是不使用Java.'为什么? – Dici 2014-08-31 15:09:51
没理由。垃圾邮件。 – 2014-08-31 15:10:36