Hubi
Hubi

Reputation: 560

Is there a way to reduce multiple methods to one method with Function<? super T, ?> as method parameter?

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

Answers (3)

Nikolas
Nikolas

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

Unikaz
Unikaz

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

Benjamin Sch&#252;ller
Benjamin Sch&#252;ller

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

Related Questions