About filters in java

How to filter a Java Collection (based on predicate)?

Java 8 (2014) solves this problem using streams and lambdas in one line of code:

List beerDrinkers = persons.stream() .filter(p -> p.getAge() > 16).collect(Collectors.toList()); 

Use Collection#removeIf to modify the collection in place. (Notice: In this case, the predicate will remove objects who satisfy the predicate):

persons.removeIf(p -> p.getAge()  

lambdaj allows filtering collections without writing loops or inner classes:

List beerDrinkers = select(persons, having(on(Person.class).getAge(), greaterThan(16))); 

Can you imagine something more readable?

Disclaimer: I am a contributor on lambdaj

Nice but the static imports obfuscate whats going on. For reference, select/having/on are static imports on ch.lambdaj.Lambda, greaterThan is org.hamcrest.Matchers

LambdaJ is really sexy, but it worths noting that it implies a significant overhead (2.6 average): code.google.com/p/lambdaj/wiki/PerformanceAnalysis.

Really like this example of LamdaJ. similar to .NET built-in Lambda functions. And where can a person drink at age 16? We should consider adding a localization constraint. 😛

Assuming that you are using Java 1.5, and that you cannot add Google Collections, I would do something very similar to what the Google guys did. This is a slight variation on Jon's comments.

First add this interface to your codebase.

public interface IPredicate

Its implementers can answer when a certain predicate is true of a certain type. E.g. If T were User and AuthorizedUserPredicate implements IPredicate , then AuthorizedUserPredicate#apply returns whether the passed in User is authorized.

Then in some utility class, you could say

public static Collection filter(Collection target, IPredicate predicate) < Collectionresult = new ArrayList(); for (T element: target) < if (predicate.apply(element)) < result.add(element); >> return result; > 

So, assuming that you have the use of the above might be

Predicate isAuthorized = new Predicate() < public boolean apply(User user) < // binds a boolean method in User to a reference return user.isAuthorized(); >>; // allUsers is a Collection Collection authorizedUsers = filter(allUsers, isAuthorized); 

If performance on the linear check is of concern, then I might want to have a domain object that has the target collection. The domain object that has the target collection would have filtering logic for the methods that initialize, add and set the target collection.

In the utility class (let's say Predicate), I have added a select method with an option for default value when the predicate doesn't return the expected value, and also a static property for params to be used inside the new IPredicate.

public class Predicate < public static Object predicateParams; public static Collection filter(Collection target, IPredicate predicate) < Collectionresult = new ArrayList(); for (T element : target) < if (predicate.apply(element)) < result.add(element); >> return result; > public static T select(Collection target, IPredicate predicate) < T result = null; for (T element : target) < if (!predicate.apply(element)) continue; result = element; break; >return result; > public static T select(Collection target, IPredicate predicate, T defaultValue) < T result = defaultValue; for (T element : target) < if (!predicate.apply(element)) continue; result = element; break; >return result; > > 

The following example looks for missing objects between collections:

List missingObjects = (List) Predicate.filter(myCollectionOfA, new IPredicate() < public boolean apply(MyTypeA objectOfA) < Predicate.predicateParams = objectOfA.getName(); return Predicate.select(myCollectionB, new IPredicate() < public boolean apply(MyTypeB objectOfB) < return objectOfB.getName().equals(Predicate.predicateParams.toString()); >>) == null; > >); 

The following example, looks for an instance in a collection, and returns the first element of the collection as default value when the instance is not found:

MyType myObject = Predicate.select(collectionOfMyType, new IPredicate() < public boolean apply(MyType objectOfMyType) < return objectOfMyType.isDefault(); >>, collectionOfMyType.get(0)); 

UPDATE (after Java 8 release):

It's been several years since I (Alan) first posted this answer, and I still cannot believe I am collecting SO points for this answer. At any rate, now that Java 8 has introduced closures to the language, my answer would now be considerably different, and simpler. With Java 8, there is no need for a distinct static utility class. So if you want to find the 1st element that matches your predicate.

final UserService userService = . // perhaps injected IoC final Optional userOption = userCollection.stream().filter(u -> < boolean isAuthorized = userService.isAuthorized(u); return isAuthorized; >).findFirst(); 

The JDK 8 API for optionals has the ability to get() , isPresent() , orElse(defaultUser) , orElseGet(userSupplier) and orElseThrow(exceptionSupplier) , as well as other 'monadic' functions such as map , flatMap and filter .

If you want to simply collect all the users which match the predicate, then use the Collectors to terminate the stream in the desired collection.

final UserService userService = . // perhaps injected IoC final List userOption = userCollection.stream().filter(u -> < boolean isAuthorized = userService.isAuthorized(u); return isAuthorized; >).collect(Collectors.toList()); 

See here for more examples on how Java 8 streams work.

Источник

Stream Filter in Java using Lambda Expressions

Java offers some sophisticated methods that make optimum use of streams and lambda expressions. These allow you to build an assembly line using functional programming principles.

One of these methods, filter(), is an intermediate operation that receives data from a stream and produces a new stream after changing the data based on a condition.

Introduction

In this guide, we will have a look at how we can use this method to its fullest extent.

Prerequisites

Before going through this tutorial the reader should:

  • Have basic knowledge of Java programming language.
  • Have some experience working with Java streams.
  • Know the basics of maven.

Table of contents

Overview of the stream filter method in java

The filter() function of the Java stream allows you to narrow down the stream’s items based on a criterion. If you only want items that are even on your list, you can use the filter method to do this. This method accepts a predicate as an input and returns a list of elements that are the results of that predicate.

It is possible to get a stream of items from this stream that meet a particular predicate with the filter() method. This is a step-between process. Performing an intermediate action like filter() does not really filter anything, but instead generates a new stream. This stream when browsed, includes the items of the first stream that satisfy the provided predicate. These operations are always lazy.

Using the Stream filter method

Java stream offers the filter() method, which allows you to filter stream elements based on a predicate you specify. You can conveniently get only even elements from your list by using the filter method. This method accepts a predicate as a parameter and returns a stream of elements that are the results of the predicate.

A stream interface’s filter() method identifies elements in a stream that satisfy a criterion. It is a stream interface intermediate operation.

The following is the method signature for the Stream filter() function:

Streamq> filter(Predicate super q> predicate) 

Notice how it accepts a predicate object as a parameter. A predicate is a logical interface to a functional interface. Therefore, you may also send a lambda expression to this function.

Collection filtering

The filter() function is often used to handle collections. We can use it to create a list of workers who have earned more than 90 marks, specifying the predicate as a lambda.

// Assume Employee to be a POJO (plain old java object) with the employee's identity and marks  Employee george = new Employee("George", 91); Employee mike = new Employee("Mike", 95);  ListEmployee> employees = List.of(  george,  mike,  new Employee("Debra", 80),  new Employee("Robbert", 50) );  ListEmployee> employeeWith90MarksAndAbove = employees  .stream()  .filter(q -> q.getMarks() > 90)  .collect(Collectors.toList()); 

Additionally, methods reference, which again is shorthand for such a lambda expression, may also be used.

Employee george = new Employee("George", 91); Employee mike = new Employee("Mike", 95);  ListEmployee> employees = List.of(  george,  mike,  new Employee("Debra", 80),  new Employee("Robbert", 50) );  ListEmployee> employeeWith90MarksAndAbove = employees  .stream()  .filter(Employee::hasOverNinetyMarks)  .collect(Collectors.toList()); 

In this particular instance, we enhance our Employee class by adding the hasOverNinetyMarks method:

public boolean hasOverNinetyMarks()   return this.marks > 90; > 

When we use these two approaches, we obtain the same result:

assert employeeWith90MarksAndAbove.contains(george) && employeeWith90MarksAndAbove.contains(mike); assert employeeWith90MarksAndAbove.size() == 2; 

The assert keyword guarantees the accuracy of any assumptions made in the program; when we execute an assertion, it is presumed to be true. If the assertion is untrue, the JVM will raise an assertion error. Be sure to set the -ea option (enable assertions) for your VM to be able to use assertions.

Filtering data based on a variety of criteria

In addition, we may utilize several criteria with the filter to our advantage.

We might, for instance, use a combination of points and names to narrow the results:

Employee george = new Employee("George", 91); Employee mike = new Employee("Mike", 95);  ListEmployee> employees = List.of(  george,  mike,  new Employee("Debra", 80),  new Employee("Robbert", 50) );  ListEmployee> georgeWith90MarksAndAbove = employees  .stream()  .filter(q -> q.getMarks() > 90 && q.getIdentity().startsWith("George"))  .collect(Collectors.toList());  assert georgeWith90MarksAndAbove.size() == 1; assert georgeWith90MarksAndAbove.contains(george) 

Explanation

We used multiple conditions with filter() such as marks and the identity of the employees.

Methods for dealing with exceptions

The filter method is used to evaluate predicates that do not throw exceptions when they are evaluated. The functional interfaces of the Java programming language do not specify any kind of exceptions, whether checked or unchecked. Functional interfaces given by the JDK are inadequate for dealing with exceptions; the resulting code becomes complex and complicated when dealing with them.

The handling of exceptions in lambda expressions shall be explored next in detail using several alternative approaches.

Using a custom wrapper

Adding a profilePictureUrl to our Employee object will be the first thing we do.

private String profilePictureUrl; 

Furthermore, we will create a simple hasValidProfilePicture() function to verify whether or not the profile picture is still valid:

public boolean hasValidProfilePicture() throws IOException   URL url = new URL(this.profilePictureUrl);  HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();  return connection.getResponseCode() == HttpURLConnection.HTTP_OK; > 

When the method hasValidProfilePicture() is called, an IOException is issued. Now, if we attempt to sort the clients based on this criterion. We will have the following.

ListEmployee> employeesWithValidProfilePicture = employees  .stream()  .filter(Employee::hasValidProfilePicture)  .collect(Collectors.toList()); 

Explanation

Filtering the employee with this method, hasValidProfile, will bring us a compilation error:

java: incompatible thrown types java.io.IOException in functional expression 

As shown in the following illustration, one way of handling it is to encapsulate it in the try-catch block.

ListEmployee> employeesWithValidProfilePicture = employees  .stream()  .filter(q ->    try   return q.hasValidProfilePicture();  > catch (IOException x)   // needs to take care of the stated exception  return false;  >  >).collect(Collectors.toList()); 

To prevent an exception generated by our predicate from being caught, you may wrap it in an unchecked exception such as from a RuntimeException.

Using ThrowingFunction

We may also make use of the ThrowingFunction library as an alternative.

Using ThrowingFunction, (which is a free open-source package that can be downloaded) we can handle checked exceptions in Java functional interfaces with relative simplicity.

The first step is to include the throwing function dependency in our pom.xml file:

   pl.touk   throwing-function   1.3  

Exception handling in predicates is simplified with the ThrowingPredicate class, which also contains the unchecked() method for encapsulating checked exceptions.

This action is illustrated below in the following code:

ListEmployee> employeesWithValidProfilePicture = employees  .stream()  .filter(ThrowingPredicate.unchecked(Employee::hasValidProfilePicture))  .collect(Collectors.toList()); 

Conclusion

In this tutorial, we have looked at how to use the filter() method in Java to filter out specific items from streams. In the process, we made use of lambda expressions to specify the predicate to filter with. In addition to that, we have also looked at the different approaches for dealing with exceptions handling.

Peer Review Contributions by: John Amiscaray

Источник

Читайте также:  Num files in php
Оцените статью