Reputation: 560
I have several methods that are basically all the same except for one method that is called in these methods.
Example:
protected List<DeadlineEntity> getEntityOneDeadlines() {
return deadLineEntityList
.stream()
.filter(m -> getEntityOneDeadlineDbs().stream().anyMatch(p -> m.getDb_4() != null && m.getDb_4().equals(p)))
.collect(Collectors.toList());
}
protected List<DeadlineEntity> getEntityTwoDeadlines() {
return deadLineEntityList
.stream()
.filter(m -> getEntityTwoDeadlineDbs().stream().anyMatch(p -> m.getDb_5() != null && m.getDb_5().equals(p)))
.collect(Collectors.toList());
}
So the only difference is the method getDB()
.
Since I don't want to have this method 10 times, I thought of writing this into a method and then controlling it via the input parameters.
My attempt looks like this:
protected List<DeadLineEntity> getDeadlines(List<Integer> deadLineDbList, Function<<? super T, ?> dbProperty) {
return deadLineEntityList
.stream()
.filter(m -> deadLineDbList.stream().anyMatch(p -> ....))
}
In method anyMatch()
I do not get further.
This is how I would want to use it:
List<DeadlineEntity> list1 = getDeadlines(getEntityOneDeadlineDbs(), EntityOne::getDb_4());
List<DeadlineEntity> list2 = getDeadlines(getEntityTwoDeadlineDbs(), EntityTwo::getDb_5());
What do you think? is this a good approach? What would be the further procedure in the getDeadlines()
method
Upvotes: 3
Views: 321
Reputation: 44476
Just use Supplier
to insert the required instance of the List
and Function
to substitute the getter from DeadlineEntity
to T
compliant with the getEntityXXX
method generic type of the returned List:
protected <T> List<DeadlineEntity> getDeadlines(Supplier<List<T>> dbProperty, Function<DeadlineEntity, T> getter) {
return deadLineEntityList
.stream()
.filter(m -> dbProperty.get()
.stream()
.anyMatch(p -> getter.apply(m) != null &&
getter.apply(m).equals(p)))
.collect(Collectors.toList());
}
List<DeadlineEntity> one = getDeadlines(this::getEntityOneDeadlineDbs, DeadlineEntity::getDb_4);
List<DeadlineEntity> two = getDeadlines(this::getEntityTwoDeadlineDbs, DeadlineEntity::getDb_5);
Edit: To make the code a bit more readable, I'd filter out all p
equal to null
first and then simplify the lambda expression and switch the parameters of the equals
call in the anyMatch
method to be null-safe:
protected <T> List<DeadlineEntity> getDeadlines(Supplier<List<T>> dbProperty, Function<DeadlineEntity, T> getter) {
return deadLineEntityList
.stream()
.filter(m -> dbProperty.get().stream()
.filter(Objects::nonNull)
.anyMatch(p -> p.equals(getter.apply(m))))
.collect(Collectors.toList());
}
Upvotes: 2
Reputation: 29
Maybe it could be easyer to pass the return of getDB to your method ? (if it's always the same type).
If you need to send a function, it seams like you should use a Supplier<T>
instead of the Function<? super T, ?>
as getBD has no parameter.
To use it, you have to use the get()
method of the Supplier class :
protected List<DeadLineEntity> getDeadlines(List<Integer> deadLineDbList, Supplier<T> dbProperty) {
return deadLineEntityList
.stream()
.filter(m -> deadLineDbList.stream()
.anyMatch(p -> dbProperty.get() != null && dbProperty.get().equals(p)))
.collect(Collectors.toList());
}
Upvotes: 1
Reputation: 2199
The filter
Method takes a Predicate
as a parameter. So you can split the predicate from the rest.
protected List<DeadlineEntity> getEntityDeadlines(Predicate filterPredicate) {
return deadLineEntityList
.stream()
.filter(filterPredicate)
.collect(Collectors.toList());
}
protected List<DeadlineEntity> getEntityOneDeadlines() {
return getEntityDeadlines(getDb4Filter());
}
protected List<DeadlineEntity> getEntityTwoDeadlines() {
return getEntityDeadlines(getDb5Filter());
}
protected Predicate<DeadlineEntity> getDb4Filter() {
return m -> getEntityOneDeadlineDbs().stream().anyMatch(p -> m.getDb_4() != null && m.getDb_4().equals(p));
}
protected Predicate<DeadlineEntity> getDb5Filter() {
return m -> getEntityTwoDeadlineDbs().stream().anyMatch(p -> m.getDb_5() != null && m.getDb_5().equals(p));
}
Upvotes: 2