2

I have an object Student

public class Student {
   String name;
   String[] classes;

    public Student(String name, String[] classes){
        this.name = name;
        this.classes = classes;
    }

   //getter & setter
}

I want to filter the classes. For example, I have

Student sa = new Student("John", "math, physics")
Student sb = new Student("Jack", "math, english")
Student sc = new Student("Maria", "math, chemistry")

So how do I get the Student with math vairable? Do I need to write a new Predicate or is there an existing method? Thank you.

3
  • Build a stream from that array and filter by that "term". Commented Apr 30, 2018 at 13:44
  • write the getter and use streams lambda with filter method Commented Apr 30, 2018 at 13:44
  • You can't just create an array from "math, physics", you need to do something like new String[]{"math", "physics"} Commented Apr 30, 2018 at 13:49

3 Answers 3

2

There is a lot wrong with your code.

First: If your constructor requires a String[] parameter, you have to provide a String[] not a String. Call it like this:

Student sa = new Student("John", new String[]{"math", "physics"});
Student sb = new Student("Jack", new String[]{"math", "english"});
Student sc = new Student("Maria", new String[]{"math", "chemistry"});

You should make your fields private and use getters, instead of making them package private. You can read about visibility here

Now, you have three Student objecs. You cant put them into a Stream the easiest way like this:

Arrays.stream(new Student[]{sa, sb, sc})

You can now filter the stream with something like this:

Arrays.stream(new Student[]{sa, sb, sc})
    .filter(s -> {
        for(String className : s.classes) {
            if(className.equals("math")) return true;
        }
        return false;
    })

Which will give you a Stream of all Students that have the class math within their classes field. You can now collect your elements or do more work with it.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use a seaparate find method to locate a class in the array:

List<Student> mathStudents = studentList.stream()
                  .filter(student -> findClass(student.getClasses(), "math"))
                  .collect(Collectors.toList());

Sorting is needed for binary search, but it's better done before the search, preferably in constructor of Student, as suggested by AlexH

private static boolean findClass(String[] classes, String search) {

    Arrays.sort(classes); 
    return 0 <= Arrays.binarySearch(classes, search);
}

1 Comment

I would suggest to sort the array in Student constructor. This would be simpler to look at chemistry later on ;)
1

Assuming you have a List<Student> populated with the correct data, you can accomplish the task at hand like so:

List<Student> result = 
     students.stream()
             .filter(student -> Arrays.stream(student.getClasses())
                                      .anyMatch("math"::equals))
             .collect(Collectors.toList());

This creates a stream from the list of students and filters them to retain only students who have a "math" class.

4 Comments

Thank you for answering. Could I ask how to filter two classes such as math and physics? Thanks!
@DexD.Hunter no probs and sure, you can do it like this --> List<Student> result = students.stream() .filter(s -> { Set<String> classes =Set.of(s.getClasses()); return classes.contains("math") && classes.contains("physics"); }) .collect(Collectors.toList());
@DexD.Hunter if you're not using java-9 then change Set<String> classes =Set.of(s.getClasses()); to List<String> classes = Arrays.asList(s.getClasses());
Works like a charm. Thank you very much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.