Java 如何预先计算有效的组合数,而不是使用while循环?
给定数据中心列表(dc1、dc2、dc3)和机器列表(h1、h2、h3、h4),如下所述-Java 如何预先计算有效的组合数,而不是使用while循环?,java,algorithm,map,while-loop,Java,Algorithm,Map,While Loop,给定数据中心列表(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} 每个过程中的每个数据中心都应获得备用
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}
每个过程中的每个数据中心都应获得备用计算机/主机。他们不应该得到同样的机器。例如,在如上所示的a
中-dc1得到h1
,dc2得到h2
,dc3得到h3
,因此每个数据中心的所有机器都不同。在第二次传递中,如b
-现在dc1得到h2
(因为dc1在第一次传递中已经得到h1),dc2得到h3
(bcoz dc2在第一次传递中已经得到h2),以及dc3得到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<String, String> coloHost = dcm.getDatacenterMachineMapping();
System.out.println(coloHost);
for (Map.Entry<String, String> entry : coloHost.entrySet()) {
}
}
}
}
class DatacenterMachineMapping {
private boolean firstCall = true;
private int hostListIndex = 0;
private List<String> datacenterList, hostList;
private Map<String, Set<String>> dataCenterHostsMap = new HashMap<String, Set<String>>();
public DatacenterMachineMapping(List<String> datacenterList, List<String> hostList) {
this.datacenterList = datacenterList;
this.hostList = hostList;
}
public Map<String, String> getDatacenterMachineMapping() {
Map<String, String> datacenterMachineMapping = new HashMap<String, String>();
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<String> dataCenterHostSet = dataCenterHostsMap.get(datacenter);
if (dataCenterHostSet == null) {
dataCenterHostSet = new HashSet<String>();
dataCenterHostsMap.put(datacenter, dataCenterHostSet);
}
return dataCenterHostSet.add(host);
}
}
公共类数据中心映射{
公共静态void main(字符串[]args){
DatacenterMachineMapping dcm=新的DatacenterMachineMapping(Arrays.asList(“dc1”、“dc2”、“dc3”)、Arrays.asList(
"h1,"h2,"h3,"h4";;
//有什么方法可以避免while循环?
while(true){
Map coloHost=dcm.getDatacenterMachineMapping();
System.out.println(coloHost);
对于(Map.Entry:coloHost.entrySet()){
}
}
}
}
类DatacenterMachineMapping{
私有布尔值firstCall=true;
私有int hostListIndex=0;
私有列表数据中心列表、主机列表;
私有映射dataCenterHostsMap=newhashmap();
公共数据中心机器映射(列表数据中心列表、列表主机列表){
this.datacenterList=datacenterList;
this.hostList=主机列表;
}
公共地图getDatacenterMachineMapping(){
Map datacenterMachineMapping=新建HashMap();
如果(!firstCall){
如果(hostListIndex不确定您在这里问了什么,但我想我可以看到问题所在,每次get-call-get-mapping您只生成一行。因此我重写了代码,使其生成所有映射,并返回映射列表。这样您就可以对它们执行所需操作
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<Map<String, String>> coloHost = dcm
.getDatacenterMachineMappings();
System.out.println(coloHost);
}
}
class DatacenterMachineMapping {
private boolean firstCall = true;
private int hostListIndex = 0;
private List<String> datacenterList, hostList;
public DatacenterMachineMapping(List<String> datacenterList,
List<String> hostList) {
this.datacenterList = datacenterList;
this.hostList = hostList;
}
public List<Map<String, String>> getDatacenterMachineMappings() {
List<Map<String, String>> grid = new ArrayList<Map<String, String>>();
for (int i = 0; i < datacenterList.size(); i++) {
Map<String, String> datacenterMachineMapping = new HashMap<String, String>();
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;
}
}
你说的是数学,答案是(n选择k),其中n是机器的数量,k是数据中心的数量
原因如下:顺序并不重要,因此我们假设数据中心总是按照相同的顺序排列。对于第一个数据中心,我们可以选择n
机器中的任何一台。对于第二个,我们可以选择任何一台机器,除了之前选择的机器,因此n*(n-1)
。下一个数据中心将导致n*(n-1)*(n-2)
可能的情况
因此,如果您有10台机器和4个数据中心,您将有:
10*9*8*7
可能的组合
更多信息请点击此处:
如果您想要一个函数为您完成工作,它位于Apache commons中:
但是,如果您确实想要生成这些组合,那么您需要一个for循环。有效组合的数量=Max(数据中心计数、机器计数)我刚刚运行了代码,它给出了java.lang.ArrayIndexOutOfBoundsException:3
。我刚刚在hostsList
中添加了一个主机,作为h5
,然后运行它。而且,如果您看到输出,它有两次dc1,两次dc2。在一行中,它应该是dc1,dc2,dc3。谢谢。我应该使用哪个Maven依赖项来实现它是这样的。这让我有点困惑。
[{h4=dc1, h1=dc1, h3=dc3, h2=dc2}, {h4=dc2, h1=dc2, h3=dc1, h2=dc3}, {h4=dc3, h1=dc3, h3=dc2, h2=dc1}]