如何预先计算有效的组合数而不是使用while循环?

给定dc1,dc2,dc3和机器列表的数据中心列表,如下所述h1,h2,h3,h4 –

Datacenters = dc1, dc2, dc3 Machines = h1, h2, h3, h4 

我想仅生成以下组合 –

 a) {dc1=h1, dc3=h3, dc2=h2} b) {dc1=h2, dc3=h4, dc2=h3} c) {dc1=h3, dc3=h1, dc2=h4} d) {dc1=h4, dc3=h2, dc2=h1} 

每个传递中的每个数据中心都应该获得备用机器/主机。 他们不应该得到相同的机器。 例如,如上所示 – dc1 gets h1dc2 gets h2dc3 gets h3因此每个数据中心的所有机器都不同。 并且在第二次通过中,如b所示 – 现在dc1 gets h2 (因为第一次通过时dc1已经得到h1), dc2 got h3 (bcoz dc2在第一次通过时已经得到了h2),而dc3 got h4 (bcoz dc3已经得到了h3在第一关)等等

还有一个例子 – 如果我只有三个主机,那么下面的组合我应该只得到 –

 Datacenters = dc1, dc2, dc3 Machines = h1, h2, h3 {dc1=h1, dc3=h3, dc2=h2} {dc1=h2, dc3=h1, dc2=h3} {dc1=h3, dc3=h2, dc2=h1} 

所以我想出了下面的代码,它完美无缺 –

 public class DataCenterMapping { public static void main(String[] args) { DatacenterMachineMapping dcm = new DatacenterMachineMapping(Arrays.asList("dc1", "dc2", "dc3"), Arrays.asList( "h1", "h2", "h3", "h4")); // is there any way to avoid while loop here? while (true) { Map coloHost = dcm.getDatacenterMachineMapping(); System.out.println(coloHost); for (Map.Entry entry : coloHost.entrySet()) { } } } } class DatacenterMachineMapping { private boolean firstCall = true; private int hostListIndex = 0; private List datacenterList, hostList; private Map<String, Set> dataCenterHostsMap = new HashMap<String, Set>(); public DatacenterMachineMapping(List datacenterList, List hostList) { this.datacenterList = datacenterList; this.hostList = hostList; } public Map getDatacenterMachineMapping() { Map datacenterMachineMapping = new HashMap(); if (!firstCall) { if (hostListIndex <= 0) { hostListIndex = hostList.size(); } hostListIndex--; } else { firstCall = false; } for (String datacenter : datacenterList) { if (hostListIndex == hostList.size()) { hostListIndex = 0; } if (addDataCenterHost(datacenter, hostList.get(hostListIndex))) { datacenterMachineMapping.put(datacenter, hostList.get(hostListIndex++)); } } hostListIndex--; return datacenterMachineMapping; } private boolean addDataCenterHost(String datacenter, String host) { Set dataCenterHostSet = dataCenterHostsMap.get(datacenter); if (dataCenterHostSet == null) { dataCenterHostSet = new HashSet(); dataCenterHostsMap.put(datacenter, dataCenterHostSet); } return dataCenterHostSet.add(host); } } 

问题陈述:-

唯一的问题是我有一个while循环,它会一直运行,

有没有什么方法可以预先计算有效组合的数量,而不是使用while循环?

你在说数学。 答案是(n选择k),其中n是机器的数量,k是数据中心的数量。

原因如下:排序并不重要,因此我们假设数据中心始终按相同的顺序排列。 对于第一个数据中心,我们可以选择n台机器中的任何一台。 对于第二种,我们可以选择任何一台机器,除了之前选择的机器,因此n * (n-1) 。 下一个数据中心将导致n * (n-1) * (n-2)可能的情况。

因此,如果您有10台机器和4个数据中心,您将拥有:

10 * 9 * 8 * 7可能的组合。

更多信息: http : //en.wikipedia.org/wiki/Combination

如果你想让一个函数为你做这项工作,它就在Apache公共场所: http : //commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/ArithmeticUtils.html #binomialCoefficientDouble%28int,%20int 29%

但是,如果您实际上想要生成这些组合,那么您需要一个for循环。

不确定你在这里问过什么,但我想我可以看到问题所在,每次调用get map你只生成1行。 所以我重写了代码,以便生成所有代码并返回一个地图列表。 所以你可以用它们做你需要的。

 public class DataCenterMapping { public static void main(String[] args) { DatacenterMachineMapping dcm = new DatacenterMachineMapping( Arrays.asList("dc1", "dc2", "dc3"), Arrays.asList("h1", "h2", "h3", "h4")); List> coloHost = dcm .getDatacenterMachineMappings(); System.out.println(coloHost); } } class DatacenterMachineMapping { private boolean firstCall = true; private int hostListIndex = 0; private List datacenterList, hostList; public DatacenterMachineMapping(List datacenterList, List hostList) { this.datacenterList = datacenterList; this.hostList = hostList; } public List> getDatacenterMachineMappings() { List> grid = new ArrayList>(); for (int i = 0; i < datacenterList.size(); i++) { Map datacenterMachineMapping = new HashMap(); String[] line = new String[hostList.size()]; for (int j = 0; j < line.length; j++) { int off = j + i; if (off >= datacenterList.size()) { off -= datacenterList.size(); } datacenterMachineMapping.put(hostList.get(j) ,datacenterList.get(off)); } grid.add(datacenterMachineMapping); } return grid; } } 

示例输出:

 [{h4=dc1, h1=dc1, h3=dc3, h2=dc2}, {h4=dc2, h1=dc2, h3=dc1, h2=dc3}, {h4=dc3, h1=dc3, h3=dc2, h2=dc1}]