I was trying to filter a list based on multiple conditions, sorting.
class Student{
private int Age;
private String className;
private String Name;
public Student(int age, String className, String name) {
Age = age;
this.className = className;
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
Now if I have a list of that, say
List<Student> students = new ArrayList<>();
students.add(new Student(24, "A", "Smith"));
students.add(new Student(24, "A", "John"));
students.add(new Student(30, "A", "John"));
students.add(new Student(20, "B", "John"));
students.add(new Student(24, "B", "Prince"));
How would I be able to get a list of the oldest students with a distinct name? In C# this would be quite simple by using System.Linq GroupBy then comparing and then flattening with select, I'm not too sure how I could achieve the same in Java.
Overview However, we'll learn how to use the filter() method with as many condition filters as we require. More filters can be applied in a variety of methods, such using the filter() method twice or supplying another predicate to the Predicate. and() method.
You can use the firstPredicate. and(secondPredicate) to filter results on multiple conditions. The first predicate receives each element from the stream. If the first predicate evaluates to true, then te second predicate receives the same element.
2.1. Multiple Filters. The Stream API allows chaining multiple filters.
If you have an ordered stream and perform operations which guarantee to maintain the order, it doesn't matter whether the stream is processed in parallel or sequential; the implementation will maintain the order.
2. Basic Sort Without Lambdas Before Java 8, sorting a collection would involve creating an anonymous inner class for the Comparator used in the sort: 3. Basic Sort With Lambda Support With the introduction of Lambdas, we can now bypass the anonymous inner class and achieve the same result with simple, functional semantics:
The if-else condition can be applied using the lambda expressions in stream filter () function. 1. Java 8 stream – if-else logic The 'if-else' condition can be put as a lambda expression in stream.forEach () function in form of a Consumer action.
GitHub link is given at the end of the article for the shown examples. 2. Stream.filter () with Single Condition First, We'll start by looking at how to apply the single filter condition to java streams. Predicate is passed as an argument to the filter () method. Each value in the stream is evaluated to this predicate logic.
An example is java.lang.Runnable). lambda expressions implement the only abstract function and therefore implement functional interfaces lambda expressions are added in Java 8 and provide below functionalities.
Use the toMap
collector:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Explanation
We're using this overload of toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
above is the keyMapper
function used to extract the values for the map keys.Function.identity()
above is the valueMapper
function used to extract the values for the map values where Function.identity()
simply returns the elements in the source them selves i.e. the Student
objects.BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldest Student
.values()
returns us a collection of students.The equivalent C# code being:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Explanation (for those unfamiliar with .NET)
We're using this extension method of GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
above is the keySelector
function used to extract the value to group by.v => v
above is the elementSelector
function used to extract the values i.e. the Student
objects them selves.b.OrderByDescending(e => e.Age).Take(1)
above is the resultSelector
which given an IEnumerable<Student>
represented as b
takes the oldest student..SelectMany(x => x);
to collapse the resulting IEnumerable<IEnumerable<Student>>
into a IEnumerable<Student>
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With