集合列表返回重复项

时间:2018-03-14 03:40:11

标签: java list collections set

嘿我正在实现这个功能。

private static HashMap<String, Set<String>> enrollments = new HashMap<String, Set<String>>();
private static Set<String> studentset;
/**
 * Enrolls a student into a unit.
 * 
 * @param unit
 * @param student
 */
public static void enroll(String unit, String student) {

    if(!enrollments.containsKey(unit)) {
        studentset = new HashSet<String>();
    }
    studentset.add(student);
    enrollments.put(unit, studentset);

}


/**
     * Gets a list of all students of a particular discipline. E.g. If discipline is
     * "ABC" then return a collection of all students enrolled in units that start
     * with "ABC", so ABC301, ABC299, ABC741 etc. This method is non-trivial so it
     * would help to first implement the helper method matchesDiscipline (below).
     * 
     * @param discipline
     * @return
     */

    public static Set<String> getStudents(String discipline) {

        Set<String> myList = new HashSet<String>();

        for (Entry<String, Set<String>> e : enrollments.entrySet()) {
            if (e.getKey().startsWith(discipline)) {

                myList.addAll(e.getValue());

            }
        }

        return myList;
    }

public static void main(String[] args) {
        EnrollmentManager.enroll("CAB302", "James");
        EnrollmentManager.enroll("CAB403", "Ben");
        EnrollmentManager.enroll("CAB302", "James");
        EnrollmentManager.enroll("CAB403", "Morgan");
        EnrollmentManager.enroll("CAB404", "Sam");
        System.out.println(EnrollmentManager.getStudents("CAB3"));
    }

我遇到的问题是&#39; myList&#39;正在输出[Morgan,James,Ben]。正确的答案是[詹姆斯]。我哪里错了?对不起,如果它是一个简单的解决方案我很新的收藏。

3 个答案:

答案 0 :(得分:3)

您的代码存在的问题是您使用的是静态studentSet变量。让我干你的代码。

您在这里做的是在找不到密钥时创建新集,否则您正在使用现有集,这是您的静态成员。

if(!enrollments.containsKey(unit)) { 
    studentset = new HashSet<String>();
}

EnrollmentManager.enroll("CAB302", "James");将创建一个新集合,假设为set1并将其分配给静态成员studentset。这一步之后的学生集{詹姆斯}。

EnrollmentManager.enroll("CAB403", "Ben");将创建一个新集合,假设为set2并将其分配给静态成员studentset。这一步之后的学生集{Ben}

EnrollmentManager.enroll("CAB302", "James"); NOT 创建一个新集并使用studentset的当前值,即set2。这一步之后的学生集{Ben,James}

EnrollmentManager.enroll("CAB403", "Morgan"); NOT 创建一个新集并使用studentset的当前值,即set2。这一步之后的学生集{Ben,James,Morgan}。 由于您的地图具有对此静态成员的引用,因此无论何时检索,您都将获得静态成员值..

您应该使用的是函数变量,而不是使用静态集成员。 并改变你的状况:

Hashset<String> studentset = null;
if(!enrollments.containsKey(unit)) { 
    studentset = new HashSet<String>();
}else{
   studentset = enrollments.containsKey(unit);
}

答案 1 :(得分:1)

您可以按以下方式更改注册方法:

public static void enroll(String unit, String student) {

    if(!enrollments.containsKey(unit)) {
        studentset = new HashSet<String>();
        enrollments.put(unit, studentset);
    } else {
        studentset = enrollments.get(unit);
    }
    studentset.add(student);

}

您的错误:您有一个静态引用private static Set<String> studentset;,在您的情况下,当!enrollments.containsKey(unit)返回false时,它会用于在地图的上一个条目中添加新学生。最佳做法是将其作为局部变量并在注册方法中进行定义。

答案 2 :(得分:1)

问题在于您的静态变量studentset,即使studentset的地图中已有unit,您也会添加到该集合中。如果找到密钥,您应该添加到地图中现有的集合。

如果您使用的是Java 8或更高版本,则可以在一行中完成:

enrollments.computeIfAbsent(unit, k -> new HashSet<>()).add(student);

你根本不需要studentset静态字段。