Java - 检查ArrayList中的重复项

3

我正在为学校生成4位数字PIN码,这些PIN码必须以4位字符字符串的形式存储在数据库中。这是我用来生成PIN码的方法:

public void generatePin() {
    String pin;
    Random r = new Random();
    for (int i = 0; i < createdStudents.size(); i++) {
        int rand = r.nextInt((3998 - 1) + 1) + 1;
        if (rand < 10) {
            pin = "000" + rand;
        } else if (rand < 100) {
            pin = "00" + rand;
        } else if (rand < 1000) {
            pin = "0" + rand;
        } else {
            pin = "" + rand;
        }
        createdStudents.get(i).setPin(pin);
    }
}

我的问题是:

如果我稍微改变上面的方法,把每个PIN添加到一个String类型的ArrayList中,那么最有效的方法是什么,以便在该列表中进行“搜索”,确保同一所学校的两个学生不会使用相同的PIN?

(说明:每个学校永远不会有超过1,200名学生)

编辑:

最终我做了以下处理:

public void generatePin() {
    List<String> pins = new ArrayList<String>();
    String pin;
    Random r = new Random();
    for (int i = 0; i < createdStudents.size(); i++) {
        int rand = r.nextInt((9999 - 1) + 1) + 1;
        if (rand < 10) {
            pin = "000" + rand;
        } else if (rand < 100) {
            pin = "00" + rand;
        } else if (rand < 1000) {
            pin = "0" + rand;
        } else {
            pin = "" + rand;
        }

        if (!pins.contains(pin)) {
            createdStudents.get(i).setPin(pin);
            pins.add(pin);
        } else {
            i--;
        }
    }
}

创建一个ArrayList来存储密码,每次生成后检查是否存在于ArrayList中。如果不存在,则分配给学生。如果存在,则将循环计数器减一以返回到刚引用的列表索引并生成新的密码。这将继续进行,直到生成唯一的密码,并将其分配给学生。

2
if(!list.contains(pin))list.add(pin); - XtremeBaumer
4
您可能希望简化您用于添加前导零的代码。请查看此链接:https://dev59.com/NW855IYBdhLWcg3wNxgM#4469748。 - Federico klez Culloca
3个回答

6

使用 Set 来记住并检查已使用的针脚,因为它不允许重复。我将生成代码的代码移入了一个单独的方法中。

public void generatePin() {
    String pin;
    Set<String> generatedPins = new HashSet<>();
    for (int i = 0; i < createdStudents.size(); i++) {
        do {
            pin = generatePinCode();
        } while (!generatedPins.add(pin));
        createdStudents.get(i).setPin(pin);
    }
}

Set用于在集合中不想要重复项的情况下使用,因为它不允许重复项,所以这是正确的做法。 - IgrewupwithSlackware
我希望我没有误解你的评论,但是是的,我使用集合的原因是它不允许重复。 - Joakim Danielson
2
确切地说,我是建议解释为什么要使用Set而不是List;我看到你添加了“因为它不允许重复项”,那么我认为现在答案已经很好地解释了 :) - IgrewupwithSlackware

0
首先,我会生成密码,然后将它们分配给每个学生。使用Set和SecureRandom以强算法(密码是敏感数据,我想...)。就像这样:

    int studentsNumber = 4;

    // Securely generate N unique pins
    Set<String> pins = new HashSet();
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    while (pins.size() != studentsNumber) {
        int pin = sr.nextInt((3998 - 1) + 1) + 1;
        String pinStr = String.format("%04d", pin);
        pins.add(pinStr);
    }

    // Set pins to the students
    for (Student s : createdStudents) {
        for (String pin : pins) {
            s.setPin(pin);
        }
    }

1
“SecureRandom” 对于这种情况可能有点过头了,你不觉得吗? - Federico klez Culloca
如果性能不佳,切换到随机模式... - cactuschibre

0

生成PIN码的代码(无更改):

public String generatePin() {
    String pin;
    Random r = new Random();
    int rand = r.nextInt((3998 - 1) + 1) + 1;
    if (rand < 10) {
        pin = "000" + rand;
    } else if (rand < 100) {
        pin = "00" + rand;
    } else if (rand < 1000) {
        pin = "0" + rand;
    } else {
        pin = "" + rand;
    }

    return pin;
}

确保分布式引脚是唯一的:
public void distributeUniquePins() {
    List<String> distributedPins = new ArrayList<>();

    createdStudents.forEach(student -> {
        String pin = generatePin();

        while(distributedPins.contains(pin)) {
            pin = generatePin();
        }

        distributedPins.add(pin);
        student.setPin(pin);
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接