iOS Swift中如何按嵌套数组(一对多关系)条件过滤对象数组
嘿,JavaJoe,我懂你在嵌套一对多关系里过滤对象时的纠结——这种多层关联的过滤确实容易绕得头大。结合你说的大学申请系统场景,我给你分两种最常见的情况来拆解解决方案,应该能帮到你:
一、内存中过滤已加载的对象集合
要是你已经把Person、School、SchoolType这些数据都加载到内存里了,用Java Stream就能轻松搞定过滤需求。先给你看个简化版的实体类结构,方便理解:
// 简化的实体类定义 class SchoolType { private String typeName; // 比如"公立大学"、"私立大学" // 省略getter、setter } class School { private SchoolType schoolType; private List<Person> applicants; // 反向关联的申请人员列表 // 省略getter、setter } class Person { private List<School> appliedSchools; // 该人员申请的学校列表 // 省略getter、setter }
场景1:筛选出至少申请过一所公立大学的人员
用两层Stream嵌套,外层过滤Person,内层检查他的申请学校里有没有符合条件的:List<Person> filteredPersons = allPersons.stream() .filter(person -> person.getAppliedSchools().stream() .anyMatch(school -> "公立大学".equals(school.getSchoolType().getTypeName())) ) .collect(Collectors.toList());场景2:筛选人员+过滤他们的申请学校(只保留符合条件的)
如果不想保留人员的所有申请记录,只留符合条件的,可以先对每个Person的学校列表做过滤,再剔除掉没有符合条件学校的人员:List<Person> personsWithFilteredSchools = allPersons.stream() .map(person -> { // 过滤当前人员的申请学校,只留公立大学 List<School> filteredSchools = person.getAppliedSchools().stream() .filter(school -> "公立大学".equals(school.getSchoolType().getTypeName())) .collect(Collectors.toList()); // 注意:*尽量不要直接修改原实体对象*,建议创建副本或者用DTO来封装结果 Person filteredPerson = new Person(); filteredPerson.setAppliedSchools(filteredSchools); // 复制其他必要属性(比如姓名、ID等) return filteredPerson; }) // 去掉那些没有符合条件学校的人员 .filter(person -> !person.getAppliedSchools().isEmpty()) .collect(Collectors.toList());
二、数据库层面过滤(以JPA/Hibernate为例)
如果数据量比较大,内存过滤效率太低,最好直接在数据库查询时就完成过滤,避免加载不必要的数据。这里以JPA为例,给你两种实现方式:
方式1:用JPQL查询符合条件的人员
通过JOIN关联三层实体,加上WHERE条件过滤,用DISTINCT避免重复的Person记录(毕竟一个人可能申请多所符合条件的学校):String jpql = "SELECT DISTINCT p FROM Person p " + "JOIN p.appliedSchools s " + "JOIN s.schoolType st " + "WHERE st.typeName = :typeName"; TypedQuery<Person> query = entityManager.createQuery(jpql, Person.class); query.setParameter("typeName", "公立大学"); List<Person> filteredPersons = query.getResultList();方式2:查询人员的同时,只加载符合条件的申请学校
默认情况下JPA会加载Person的所有关联学校,如果想只返回符合条件的学校,可以用FETCH JOIN:String jpql = "SELECT DISTINCT p FROM Person p " + "JOIN FETCH p.appliedSchools s " + "JOIN s.schoolType st " + "WHERE st.typeName = :typeName"; TypedQuery<Person> query = entityManager.createQuery(jpql, Person.class); query.setParameter("typeName", "公立大学"); List<Person> filteredPersons = query.getResultList();这样查询出来的Person对象,它的
appliedSchools集合里就只有公立大学的记录了,不会包含其他类型的学校。
小提醒
- 数据库过滤比内存过滤效率高,尤其是数据量大的时候,优先考虑这种方式。
- 用JPA时注意关联关系的懒加载设置,避免出现N+1查询的性能问题。
- 处理过滤后的结果时,尽量用DTO(数据传输对象)来返回,不要直接修改原实体,避免影响后续的数据库操作。
内容的提问来源于stack exchange,提问作者JavaJoe
相关产品推荐
相关产品推荐

