列表中的唯一数字

huangapple go评论106阅读模式
英文:

Unique numbers in list

问题

你好,我在生成10000000名员工时遇到了问题。每个人都必须有唯一的ID号。

    List<Employee> employeesL = new LinkedList<>();

    for (var i = 0; i < 1000000; i++) {
            Employee employeeObject = new Employee();
            employeeObject.setId(Math.abs(gen.nextLong()));
            .
            .
            .
            employeesL.add(employeeObject);
    }

有没有比简单的while循环更好的方法?我尝试过像这样的方法:

    public static void uniqueAdd(List<Employee> employees, Employee employee) {
        Random gen = new Random();
        employee.setId(Math.abs(gen.nextLong()));

        while (employees.contains(employee.getId())) {
            employee.setId(Math.abs(gen.nextLong()));
        }
    }

唯一的问题是,使用这种方法生成那么多员工需要很长时间。
我也不能简单地使用迭代id++。

编辑:
我需要创建uniqueAdd方法!我的教授给了我一个建议,说我可以使用Set,例如HashSet。

英文:

Hello i have a problem with generating 10000000 employees. Everyone has to have unique ID number.

List&lt;Employee&gt; employeesL = new LinkedList&lt;&gt;();

for (var i = 0; i &lt; 1000000; i++) {
        Employee employeeObject = new Employee();
        employeeObject.setId(Math.abs(gen.nextLong()));
        .
        .
        .
        employeesL.add(employeeObject);
        }

Is it possible to do it better than simple while loop. I dit something like that:

public static void uniqueAdd(List&lt;Employee&gt; employees, Employee employee)
    {
        Random gen = new Random();
        employee.setId(Math.abs(gen.nextLong()));

        while (employees.contains(employee.getId())) {
            employee.setId(Math.abs(gen.nextLong()));
        }
    }

The only problem is that it takes forever with that method to generate that amount of employees.
I cant also use simple iteration id++

EDIT:
I need to create uniqueAdd method! My professor gave me advice that i can use Set, for example HashSet

答案1

得分: 1

你的做法是非性能优化的,因为你每次想要添加一个ID时都在检查 employees.contains(employee.getId())。最简单的方法是在 Employee 类中创建一个 static 变量,然后按以下方式获取下一个ID:

private static int id = 0;

public static int nextId() {
   return ++id;
}

然后,在循环中使用:

for (var i = 0; i < 1000000; i++) {
    Employee employeeObject = new Employee();
    employeeObject.setId(Employee.nextId());
    // ...
    employeesL.add(employeeObject);
}

你甚至可以在构造函数中分配 id,如下所示:

this.id = nextId();

这样一来,当你创建一个员工对象时,就不需要调用 employeeObject.setId(Employee.nextId()),对象会自动分配一个唯一的 id

另外一种方法是,

在填充了列表 employeesL 后,你可以使用以下机制来设置 id

Set<Integer> idSet = new HashSet<Integer>();
Random random = new Random();
while (idSet.size() != 10000000) {
    idSet.add(random.nextInt(Integer.MAX_VALUE));
}
System.out.println("生成了10000000个唯一的ID");

int i = 0;
for (Integer id: idSet) {
    employeesL.get(i).setId(id);
    i++;
}
如有疑问/问题请随意进行评论
英文:

The way you have done is a non-performant way as you are checking employees.contains(employee.getId()) every time you want to add an ID. The easiest way will be to create a static variable in Employee and get the next ID as follows:

private static int id = 0;

public static int nextId() {
   return ++id;
}

Then,

for (var i = 0; i &lt; 1000000; i++) {
	Employee employeeObject = new Employee();
	employeeObject.setId(Employee.nextId());
	.
	.
	.
	employeesL.add(employeeObject);
}

You can even assign the id in the constructor as follows:

this.id = nextId();

This way, you do not have to call employeeObject.setId(Employee.nextId()) when you create an Employee object and a unique id will automatically be assigned to the object.

Alternatively,

Once you have populated the list, employeesL, you can use the following mechanism to set the id.

Set&lt;Integer&gt; idSet = new HashSet&lt;Integer&gt;();
Random random = new Random();
while (idSet.size() != 10000000) {
    idSet.add(random.nextInt(Integer.MAX_VALUE));
}
System.out.println(&quot;10000000 unique IDs generated&quot;);

int i = 0;
for (Integer id: idSet) {
	employeesL.get(i).setId(id);
	i++;
}

Feel free to comment in case of any doubt/issue.

答案2

得分: 1

代替生成随机数并检查数字是否已在列表中,您可以为每个员工生成一个 UUID(通用唯一标识符),以确保 ID 不会重复。生成 UUID 有多种方法,但您可以像这样操作:

employeeObject.setId(UUID.randomUUID());
英文:

Instead of generating a random number and checking if the number is already in the List, you can generate a uuid (universally unique identifier) for each employee, ensuring that the id will not be repeated. There are more ways to generate uuids, but you can do something like this:

employeeObject.setId(UUID.randomUUID());

答案3

得分: 1

如果您初始化一个id候选列表,可以通过以下方法随机分配它们,且时间复杂度为常数。该方法的原理是,通过将已选id的位置替换为列表中的最后一个id来完成分配。它还会移除可能id列表中的最后一个元素,以减少不必要的存储。

	final static int MAX_IDS = 10_000_000;
	static List<Integer> ids = new ArrayList<>(MAX_IDS);
	static {
		for (int i = 0; i < MAX_IDS; i++) {
			ids.add(i + 1);
		}
	}
	final static Random r = new Random();
	
	public static int getNextID() {
		 int idsRemaining = ids.size();
		 int index = r.nextInt(idsRemaining);
		 int id = ids.get(index);
		 int last = ids.get(idsRemaining-1);
		 ids.set(index, last);
		 ids.remove(idsRemaining-1);
		 return id+1;
	}

如果您想要确保不会生成重复的id,您可以将所有的id放入一个集合中。该集合的大小应与初始列表相同,并具有相同的id,但是是随机生成的。

		Set<Integer> set = new HashSet<>(MAX_IDS);
		for (int i = 0; i < MAX_IDS; i++) {
			set.add(getNextID());
		}
		System.out.println(set.size());
英文:

If you initialize a list of id candidates you can allocate them randomly in constant time by using the following approach. It works by replacing the taken id's slot with the last id in the list. It also removes the last element in the list of possible ids to reduce unnecessary storage.

	final static int MAX_IDS = 10_000_000;
	static List&lt;Integer&gt; ids = new ArrayList&lt;&gt;(MAX_IDS);
	static {
		for (int i = 0; i &lt; MAX_IDS; i++) {
			ids.add(i + 1);
		}
	}
	final static Random r = new Random();
	
	public static int getNextID() {
		 int idsRemaining = ids.size();
		 int index = r.nextInt(idsRemaining);
		 int id = ids.get(index);
		 int last = ids.get(idsRemaining-1);
		 ids.set(index, last);
		 ids.remove(idsRemaining-1);
		 return id+1;
	}

If you want to convince yourself that no duplicates are generated, you can put all the ids in a set. The set should be the same size as the initial list and have the same ids, but randomly generated.

		Set&lt;Integer&gt; set = new HashSet&lt;&gt;(MAX_IDS);
		for (int i = 0; i &lt; MAX_IDS; i++) {
			set.add(getNextID());
		}
		System.out.println(set.size());
		 

</details>



huangapple
  • 本文由 发表于 2020年3月16日 01:33:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/60695748.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定