Java Stream操作嵌套自定义类:查询指定手机号的学生
Java Stream 筛选学生手机号问题解决方案
需求说明
现有包含自定义Address类和MobileNumber类的Student对象列表,每个Student实例持有一个MobileNumber列表,需实现两个筛选需求:
- 筛选出拥有手机号"3333"的所有学生
- 筛选出同时拥有手机号"1233"和"1234"的所有学生
原代码问题分析
- 第一个需求的实现中,
forEach(student -> student.getName())仅调用了获取姓名的方法,未对筛选结果进行收集或输出,无法得到有效结果。 - 第二个需求的实现逻辑错误:
anyMatch中判断单个手机号同时等于"1233"和"1234",这在逻辑上不可能成立,导致筛选结果为空。
正确实现代码
完整可运行代码
import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class StreamsGalore { public static void main(String[] args) { Student student1 = new Student("Jayesh", 20, new Address("1234"), Arrays.asList(new MobileNumber("1233"), new MobileNumber("1234"))); Student student2 = new Student("Khyati", 20, new Address("1235"), Arrays .asList(new MobileNumber("1111"), new MobileNumber("3333"), new MobileNumber("1233"))); Student student3 = new Student("Jason", 20, new Address("1236"), Arrays.asList(new MobileNumber("3333"), new MobileNumber("4444"))); List<Student> students = Arrays.asList(student1, student2, student3); /***************************************************** * 需求1:获取所有拥有手机号"3333"的学生 *****************************************************/ List<Student> studentsWith3333 = students.stream() .filter(student -> student.getMobileNumbers().stream() .anyMatch(mobile -> mobile.getNumber().equals("3333"))) .collect(Collectors.toList()); System.out.println("拥有手机号3333的学生:"); studentsWith3333.forEach(System.out::println); /***************************************************** * 需求2:获取同时拥有手机号"1233"和"1234"的学生 *****************************************************/ // 先定义目标手机号集合 Set<String> targetNumbers = Set.of("1233", "1234"); List<String> studentsWithBothNumbers = students.stream() .filter(student -> { // 提取当前学生的手机号集合 Set<String> studentNumbers = student.getMobileNumbers().stream() .map(MobileNumber::getNumber) .collect(Collectors.toSet()); // 检查是否包含所有目标手机号 return studentNumbers.containsAll(targetNumbers); }) .map(Student::getName) .collect(Collectors.toList()); System.out.println("\n同时拥有手机号1233和1234的学生姓名:"); System.out.println(studentsWithBothNumbers); } } class Address { private String zipcode; public Address(String zipcode) { this.zipcode = zipcode; } public String getZipcode() { return zipcode; } public void setZipcode(String zipcode) { this.zipcode = zipcode; } @Override public String toString() { return "Address{" + "zipcode='" + zipcode + '\'' + '}'; } } class MobileNumber { private String number; public MobileNumber(String number) { this.number = number; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } @Override public String toString() { return "MobileNumber{" + "number='" + number + '\'' + '}'; } } class Student { private String name; private int age; private Address address; private List<MobileNumber> mobileNumbers; public Student(String name, int age, Address address, List<MobileNumber> mobileNumbers) { this.name = name; this.age = age; this.address = address; this.mobileNumbers = mobileNumbers; } public String getName() { return name; } public int getAge() { return age; } public Address getAddress() { return address; } public List<MobileNumber> getMobileNumbers() { return mobileNumbers; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void setAddress(Address address) { this.address = address; } public void setMobileNumbers(List<MobileNumber> mobileNumbers) { this.mobileNumbers = mobileNumbers; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", address=" + address + ", mobileNumbers=" + mobileNumbers + '}'; } }
代码说明
需求1实现:
- 使用
stream().filter()结合anyMatch()判断学生的手机号列表中是否存在"3333" - 用
collect(Collectors.toList())收集筛选后的学生对象,方便后续输出或使用
- 使用
需求2实现:
- 先创建目标手机号的
Set集合targetNumbers - 对每个学生,提取其所有手机号转为
Set集合 - 使用
containsAll()方法判断学生的手机号集合是否包含所有目标号码,确保同时拥有两个手机号
- 先创建目标手机号的
内容的提问来源于stack exchange,提问作者LittleZoski
相关产品推荐
相关产品推荐

