我不知道你问题的所有细节,但我的直觉是你可能在想太多了。你计划在这个数据结构中存储多少对象?如果你需要存储大量数据,我建议你使用实际的数据库而不是数据结构。你所描述的操作类型是关系型数据库擅长处理的典型例子。
MySQL和
PostgreSQL是大规模关系型数据库的例子,它们可以轻松地完成这种操作。如果你需要更轻量级的解决方案,
SQLite可能会符合你的需求。
如果你没有大量数据需要存储在这个数据结构中,我建议保持简单,只有在确定它无法满足你的需求时再进行优化。作为第一步,我建议使用Java内置的List接口来存储你的人员,使用Map来存储组。你可以像这样做:
List<Person> myPeople = new ArrayList<Person>();
Person steve = new Person("Steve");
myPeople.add(steve);
myPeople.add(new Person("Bob"));
Map<String, List<Person>> groups = new HashMap<String, List<Person>>();
groups.put("Everybody", myPeople);
groups.put("Developers", Arrays.asList(steve));
groups.get("Everybody").containsAll(myPeople);
groups.get("Developers").containsAll(myPeople);
这绝对不是可用的最快选项,但如果您没有大量要跟踪的人员,您可能甚至不会注意到任何性能问题。如果您有一些特殊条件,使得使用常规列表和映射的速度不可行,请发布它们,我们可以根据那些提出建议。
编辑:
阅读您的评论后,看起来我初次运行时误读了您的问题。看起来您不是那么关心将组映射到人员,而是将人员映射到组。您可能需要像这样的东西:
Map<Person, List<String>> associations = new HashMap<Person, List<String>>();
Person steve = new Person("Steve");
Person ed = new Person("Ed");
associations.put(steve, Arrays.asList("Everybody", "Developers"));
associations.put(ed, Arrays.asList("Everybody"));
boolean sharesGroups = checkForSharedGroups(associations, Arrays.asList(steve, ed));
那么你如何实现checkForSharedGroups方法呢?在你的情况下,由于周围的数字相当低,我建议你尝试朴素的方法并从那里开始。
public boolean checkForSharedGroups(
Map<Person, List<String>> associations,
List<Person> peopleToCheck){
List<String> groupsThatHaveMembers = new ArrayList<String>();
for(Person p : peopleToCheck){
List<String> groups = associations.get(p);
for(String s : groups){
if(groupsThatHaveMembers.contains(s)){
return false;
} else {
groupsThatHaveMembers.add(s);
}
}
}
return true;
}
这种方法在大型数据集上可能表现不佳,但很容易理解。由于它封装在自己的方法中,如果需要更好的性能,也很容易更新。如果确实需要提高性能,建议查看
覆盖 Person 的 equals 方法,这将使关联映射中的查找更快。从那里,您还可以查看自定义类型而不是 String 用于 groups,同样具有覆盖的 equals 方法。这将显著加速以上使用的 contains 方法。
我不太关心性能的原因是,就算对于算法来说,你提到的数字并不是很大。因为该方法一旦找到两个匹配的组就会返回,所以最坏的情况下,您将调用 ArrayList.contains 的次数等于存在的组数。在最好的情况下,只需要调用两次。仅当您非常频繁地调用 checkForSharedGroups 时,性能才可能成为问题,在这种情况下,您最好找到一种方法来减少其调用次数,而不是优化方法本身。