While using filter method on Java, one of the main problem I faced is whether is filter in or filter out. I mean why I apply filter method I get a Stream back but many people including me get confused whether it contain elements which pass the filter or fail the filter.
To solve that problem, I think and remember filter() as allow() method which means any element which pass the condition will be available after filter. There may be a better way to remember how filter works in Java but this method is working for me so far.
And, now it's time to go back to filter method and learn how you can use it to filter null, empty string, and elements with any condition you want.
How to filter all null String from a List?
Here is an example of filtering out null elements from a List using Stream.filter() method in Java:
List<String> techGiants = new ArrayList<>(Arrays.asList("SONY",
"GOOGLE", "APPLE", null, ""));
techGiants.stream()
.filter(Objects :: nonNull)
.forEach(System.out::println); // SONY, GOOGLE, APPLE, ""
The List contained "SONY", "GOOGLE", "APPLE", null, "" but after filtering it only contains SONY, GOOGLE, APPLE, "". In this example though I have only printed the value from Stream so there won't be any impact on original List but you can also collect the result in another List and assigned to the same reference variable like shown below:
List<String> withoutNulls = techGiants.stream()
.filter(Objects :: nonNull)
.collect(Collectors.toList());
How to filter all null and empty String from List?
We can use the same pipeline as shown above and then add another condition to filter empty String as shown below:List<String> techGiants = new ArrayList<>(Arrays.asList("SONY",
"GOOGLE", "APPLE", null, ""));
techGiants.stream()
.filter(Objects :: nonNull)
.filter( s->> !s.isEmpty())
.forEach(System.out::println);
This will only print, SONY, GOOGLE, and APPLE as both null and empty String are filtered out. Though, you can also combine both condition at same filter method as well, which I think would be slightly more efficient as shown below:
List<String> techGiants = new ArrayList<>(Arrays.asList("SONY",
"GOOGLE", "APPLE", null, ""));
List<String> withoutNullsAndEmptyString
= techGiants.stream()
.filter(Objects :: nonNull && String :: isEmpty())
.collect(Collectors.toList());
You can write the code you feel better but when you use Stream pipeline, I think keeping condition simple improves readability.
How to chaining of filter by combining multiple predicates
You can even combine multiple predicates to do more advanced filtering e.g. to filter all String which are null or empty you can do something like shown in above example but you are free with conditions, you can use whatever condition you want.
For example, you can also filter based upon String as shown below:
ist<String> withoutNullsAndStringWithFiveOrMoreCharacters =
techGiants.stream()
.filter(Objects :: nonNull)
.filter(s->> s.length() >= 5)
.forEach(System.out::println); // GOOGLE, APPLE
You can see that here we have combined two filter() methods, you can combine as many as you want, you can even combine filter with map() and flatMap method but make sure your pipeline is not very complex and read nice otherwise it would be very difficult for any person to read and understand what is going on.
Also, here is a nice diagram of creating Stream pipeline in Java and how it works:
Java Program to use filter() method in Java 8
Here is a complete Java program which demonstrate the use of filter method in Java 8.import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* Java Program to show how to use filter() method of Java 8 Stream.
* By using filter() method you can remove unwanted elements from
* original stream or list. filter() accepts a boolean method, only elements
* for which this method return true are included into result.
*
* @author WINDOWS 10
*/
public class Java8Demo {
public static void main(String args[]) {
List<String> techGiants = new ArrayList<>(Arrays.asList("SONY",
"GOOGLE", "APPLE", null, ""));
// let's filter out null elements and print rest
techGiants.stream()
.filter(Objects :: nonNull)
.forEach(System.out::println); // SONY, GOOGLE, APPLE, ""
// let's filter out both empty and null String
techGiants.stream()
.filter(Objects :: nonNull)
.filter( s->> !s.isEmpty())
.forEach(System.out::println); // SONY, GOOGLE, APPLE
// let's filter out String whose length is less than 5
techGiants.stream()
.filter(Objects :: nonNull)
.filter(s->> s.length() >= 5)
.forEach(System.out::println); // GOOGLE, APPLE
}
}
Important things to remember
1) filter is evaluated lazily i.e. when a terminal operation is called e.g. forEach(), reduce() etc.
2) filter method is defined in java.util.stream.Stream() class
3) You can also call filter with parallel stream
Let's consider a simple example where we have a method which return a Socket connection if its connected or return a new SocketConnection, I will write code using both if condition and filter method and you let me know which method you find it better while reading code? Let me know in comments and if you can mention why, would be even better.
private static Socket getActiveOrNewSocket(Supplier<Socket> socketSupplier) {
return Optional.ofNullable(socketSupplier.get())
.filter(Socket::isConnected)
.orElseGet(() -> createNewSocket("localhost", PORT));
}
In this case, not just filter() but also Optional is there which many Java developer may not find so easy to read but you can achieve the same functionality using traditional if statements instead of Optional.
private static Socket getActiveOrNewSocket(Supplier<Socket> socketSupplier) {
Socket socket = socketSupplier.get();
if (socket != null && socket.isConnected()) {
return socket;
} else {
return createNewSocket("localhost", PORT);
}
}
That's all about how to filter elements form list and map in Java using Stream.filter() method. It's very efficient because its evaluated lazily. You can even chain multiple filters for more advanced filtering. I recommend every Java developer to master this method as it also help you write functional style of code because you will find filter almost in every single Stream pipeline.
Other Java 8 Lambda and Stream Tutorials You may like
- How to do Map Reduce in Java 8?
- Java 8 filter + map + collect example
- 10 examples of the forEach() method in Java 8?
- 3 ways to read a file line by line in Java 8
- Top 5 Books to Learn Java 8 Better
- 10 Courses to learn Java for Beginners
- My favorite courses to learn Software Architecture
- 10 examples of converting a List<V> to Map of <K, V> in Java 8?
- 10 Free Courses to learn Spring Framework for Beginners
- How to use flatMap in Java 8?
- How to pass the Java SE 11 Certification Exam
Thanks for reading this tutorial so far. If you like this Java 8 Stream and filter method tutorial then please share it with your friends and colleagues. If you
have any questions or feedback then please drop a note.
No comments:
Post a Comment
Feel free to comment, ask questions if you have any doubt.