我有以下类:
public class School{
List<ClassRoom> classRooms;
}
public class ClassRoom{
List<Student> students;
}
public class Student{
String name;
List<Long> typeIdList;
}
我只需要得到typeId
,这是给定教室S内所有学生的共同因素。
为了能够让所有学生都在指定的ID=123的教室S内,我做了以下操作:
final long typeIdToSearchFor = ...;
Collection<Student> filtered = Collections2.filter(students,
new Predicate<Student>() {
@Override
public boolean apply(Student s) {
return s.typeId == typeIdToSearchFor;
}
}
);
只是想知道番石榴能不能处理这样的事情?交叉点的意思是,它必须出现在所有实例中才能考虑这种类型。
我知道for
循环会更可读,但我只是发现了Guava的功能。
您可以使用Multiset
来计数出现次数:
ClassRoom classRoom = /* comes from somewhere */;
List<Student> students = classRoom.getStudents();
// Aggregate all the typeIds.
Multiset<Long> typeIds = HashMultiset.create();
for (Student student : students) {
// Assuming a student doesn't have duplicated typeIds:
typeIds.addAll(student.getTypeIds());
}
// Find which typeIds are present for all the students.
for (Multiset.Entry<Long> entry : typeIds.entrySet()) {
if (entry.getCount() == students.size()) {
System.out.println(entry.getElement());
}
}
如果要检查所有Student
是否都有特定的typeId
,请将Iterables.all
与现有谓词一起使用。
您还可以使用Multimaps.index()
:创建由typeId
索引的Student
的Multimap
Multimap<Long, Student> studentsByTypeId = Multimaps.index(students, new Function<Student, Long>() {
public Long apply(Student s) {
return s.typeId;
}
};
然后使用studentsByTypeId.keySet()
可以获得唯一的typeId
s。
您可以使用studentsByTypeId.keySet().size() == 1
检查它们是否都共享相同的typeId
。
如果你想要相交的,你不应该与特定的进行比较,你至少应该检查它是否包含在另一个集合的id中。像这样:
new Predicate<Student>() {
@Override
public boolean apply(Student s) {
return otherIds.contains(s.typeId);
}
}
但我仍然认为,如果你对这两个集合进行二进制搜索(排序后(,你可以更快地得到答案。像这样的
Collections.sort(list1);
Collections.sort(list2);
List<E> intersected = new ArrayList<E>();
for(E element : list1){
if(Collections.binarySearch(list2, element) >= 0){
intersected.add(element);
}
}
你甚至可以找到一种方法来完成最小的列表。它可以帮助它获得一些性能。