如果1个实例具有相同(最小)的值,如何从确定最小值的循环中随机选择一个对象?

问题描述 投票:1回答:3

我编写了一个包含三个相关类的Java程序;员工,客户和合同。在我的main方法中,我创建了一个包含所有3个类的各种实例的数组;

// Create Clients
Client Client1 = new Client(1, "Client 1", 0);
Client Client2 = new Client(2, "Client 2", 0);

// Create Array of Clients
Client[] clients = new Client[] {Client1, Client2};

// Create Contracts
Contract Contract1 = new Contract("Contract 1", 1, 850, 4, 0, 1, 0);
Contract Contract2 = new Contract("Contract 2", 2, 500, 4, 0, 1, 0);
Contract Contract3 = new Contract("Contract 3", 3, 1500, 3, 0, 1, 0);

// Create Array of Contracts
Contract[] contracts = new Contract[] {Contract1, Contract2, Contract3};

// Create Employees
Employee Employee1 = new Employee(1, "Bradley", 0);
Employee Employee2 = new Employee(2, "Patrick", 0);
Employee Employee3 = new Employee(3, "Erin", 0);
Employee Employee4 = new Employee(4, "Jim", 0);
Employee Employee5 = new Employee(5, "Fredrick", 0);

// Create Array of Employees
Employee[] employees = new Employee[] {Employee1, Employee2, Employee3, Employee4, Employee5};

我在Contract.Java中有一个名为assignContractToEmployeeWithLeastContracts的函数,它接受2个参数,一组雇员和合同。功能是:

// Assign contract to employee with least contracts
public void assignContractToEmployeeWithLeastContracts(Employee[] employees, Contract contract) {

    // Assign to employee with minimum contracts
    int minContract = Integer.MAX_VALUE;
    Employee employeeWithMinContracts = null;
    for (Employee employee : employees) {
        if (employee.getCurrentlyAssignedContracts() < minContract) {
            // swap min and employee if true
            employeeWithMinContracts = employee;
            minContract = employeeWithMinContracts.getCurrentlyAssignedContracts();
        }
    }

    employeeWithMinContracts.assignContract(employeeWithMinContracts, contract);
}

我遇到的问题是,我需要处理如果2名员工分配的合同数量相同(最小)的情况。如果发生这种情况,我该如何随意挑选一名员工?我已经尝试在foreach循环中实现种子但是不断破坏一切。

任何帮助,将不胜感激,

谢谢,B

java arrays random foreach seed
3个回答
1
投票

如果您使用的是Java 8或更高版本,则可能更具可读性:

public void assignContractToEmployeeWithLeastContracts(Employee[] employees, Contract contract) {
    int minContract =  Arrays.stream(employees)
            .mapToInt(Employee::getCurrentlyAssignedContracts)
            .min()
            .getAsInt();
    Employee employeeWithMinContracts = Arrays.stream(employees)
            .filter(e->e.getCurrentlyAssignedContracts() == minContract)
            .findAny()
            .get();

    employeeWithMinContracts.assignContract(employeeWithMinContracts, contract);
}

编辑

虽然上面解决方案中的findAny()表现出明确的非确定性,即可以自由选择流中的任何元素,这使您无法控制元素被选择的可能性;您可能希望具有均匀分布的概率。如果是这种情况,请参阅下面的第二个解决方案:

public void assignContractToEmployeeWithLeastContracts(Employee[] employees, Contract contract) {
    int minContract =  Arrays.stream(employees)
            .mapToInt(Employee::getCurrentlyAssignedContracts)
            .min()
            .getAsInt();
    List<Employee> minEmployees =  Arrays.stream(employees)
            .filter(e->e.getCurrentlyAssignedContracts() == minContract)
            .collect(Collectors.toList());

    Random r = new Random();
    Employee employeeWithMinContracts = minEmployees.get(r.nextInt(minEmployees.size()));

    employeeWithMinContracts.assignContract(employeeWithMinContracts, contract);
}

3
投票

如果您希望两个以上的员工共享相同数量的最低合同,那么您需要在其中随机选择。您可以通过列出最小合同并随机选择一个来完成此操作。

    // Assign contract to employee with least contracts
public void assignContractToEmployeeWithLeastContracts(Employee[] employees, Contract contract) {

    // Find the employees with the minimum contracts
    int minContract = Integer.MAX_VALUE;
    List <Employee> employeesWithMinContracts = new ArrayList<Employee>();
    for (Employee employee : employees) {
        //add duplicates to the list
        if (employee.getCurrentlyAssignedContracts() == minContract) {
            employeesWithMinContracts.add(employee);
        }
        // swap min and employee if true
        if (employee.getCurrentlyAssignedContracts() < minContract) {
            employeesWithMinContracts.clear();
            employeesWithMinContracts.add(employee);
            minContract = employee.getCurrentlyAssignedContracts();
        }
    }

    //Randomly pick an employee from the group.
    int random = (int)(Math.random() *  employeesWithMinContracts.size() );

    employeeWithMinContracts.assignContract(employeesWithMinContracts.get(random), contract);
}

2
投票

如果我理解正确,在您的assignContractToEmployeeWithLeastContracts方法中,如果合同数量相同,您希望将合同随机分配给其中一个员工。 因为目前您将把它分配给合同数量最少的第一个员工。

您的方法将成为这样:

public void assignContractToEmployeeWithLeastContracts(Employee[] employees, Contract contract) {
    int minContract = Integer.MAX_VALUE;
    List<Employee> employeesWithMinContracts = new ArrayList<Employee>();
    for (Employee employee : employees) {
        if (employee.getCurrentlyAssignedContracts() < minContract) {
            employeesWithMinContracts.clear();
            employeesWithMinContracts.add(employee);
            minContract = employee.getCurrentlyAssignedContracts();
        } else if (employee.getCurrentlyAssignedContracts() == minContract) {
            employeesWithMinContracts.add(employee);
        }
    }
    int randomIndex = (int)(Math.random() * employeesWithMinContracts.size());
    employeesWithMinContracts.get(randomIndex).assignContract(contract);
}

我们将利用Math.random返回[0,1]之间的值这一事实,从而随机找到我们的employeesWithMinContracts列表索引。

备注:

  • 请注意,我删除了Employee作为assignContract方法的参数。因为这个方法已经被问到了Employee
  • 此外,您的实例名称应以小写字母开头,以符合Java标准: Contract1成为contract1 Employee1成为employee1 等等...
© www.soinside.com 2019 - 2024. All rights reserved.