【问题标题】:Filter ArrayLists that just have intersected data过滤仅具有相交数据的 ArrayList
【发布时间】:2013-04-22 12:47:58
【问题描述】:

我有以下课程:

public class School{
    List<ClassRoom> classRooms;
}

public class ClassRoom{
    List<Student> students;
}

public class Student{
    String name;
    List<Long> typeIdList;
}

我只需要得到typeId,这是给定教室S内所有学生的共同因素。

为了能够让 typeID=123 的给定教室 S 中的所有学生,我执行以下操作:

final long typeIdToSearchFor = ...;
Collection<Student> filtered = Collections2.filter(students,
    new Predicate<Student>() {
        @Override
        public boolean apply(Student s) {
            return s.typeId == typeIdToSearchFor;
        }
    }
);

只是想知道 Guava 是否可以处理这样的事情? 我所说的交集是指在所有情况下都必须考虑这种类型。

我知道for 循环更具可读性,但我只是发现了 Guava 功能。

【问题讨论】:

  • 我对你的要求有点困惑。您是否要检查集合中的所有学生是否具有相同的typeId?一个特定的typeId?您所拥有的已经是一个 Guava 解决方案,用于获取具有指定 typeId 的所有 Students。
  • 这是什么Predicate ?番石榴还是 Apache Commons?
  • @Mark:我只需要获取所有学生通用的typID
  • @Echo:当每个学生只能有一个typeId 时,我不明白两个不同的typeIds 对所有学生来说是如何通用的。这没有意义。
  • @Echo 我必须同意马克的观点。你能提供一个你想要实现的例子吗?

标签: java collections guava


【解决方案1】:

您可以使用 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());
    }
}

【讨论】:

    【解决方案2】:

    如果您要检查所有Students 是否具有特定的typeId,请将Iterables.all 与现有谓词一起使用。

    您还可以使用Multimaps.index() 创建由typeId 索引的Students 的Multimap

    Multimap<Long, Student> studentsByTypeId = Multimaps.index(students, new Function<Student, Long>() {
      public Long apply(Student s) {
        return s.typeId;
      }
    };
    

    然后你可以使用studentsByTypeId.keySet()获得唯一的typeIds。

    您可以使用studentsByTypeId.keySet().size() == 1 检查它们是否都共享相同的typeId

    【讨论】:

      【解决方案3】:

      如果您想要相交的那些,则不应与特定的进行比较,您至少应该检查它是否包含在另一个集合的 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);
          }
      }
      

      您甚至可以找到最小的列表。它可以帮助它获得一些性能。

      【讨论】:

      • 您的解决方案很好,但如果我有动态数量的列表,则需要一些努力。
      • 还是可以的。如果您有动态数量的列表,我强烈建议您考虑一种执行此操作的方法,我将尝试编辑我的答案以获得包含多个集合的解决方案。你想要它们之间的交叉点吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 1970-01-01
      相关资源
      最近更新 更多