Search code examples
javalambdafunctional-interface

How to define lambda function that are similar (vary in one function) in java


I need some help. I created a functional interface that has one abstract method called filter:

@FunctionalInterface
interface FileFilter {
    /**
     * This method gets a file path and filters it in some method.
     * @return a list of the remaining files after this filter.
     * @throws IOException
     */
    abstract boolean filter(Path path) throws IOException;
}

I need to create a few different implementations of this method devided into two groups: 1. A few that filter by different file sizes (the difference between them is the criterion). 2. A few that filter by different file name. (the only difference between them is a single choice of String method - contains / startsWith etc.

It seems stupid to me to create a different function that implements my filter method for each of these when they are so similar, but I can't think of a way to overcome this. I would like to write one function (the returns a correct lambda) for each group.

For example, right now the methods that create filters from the second group look like this:

   static FileFilter prefixFilter(String[] parameters, int expectedLength) throws
            BadParameterFilterException{
        String value = parameters[0];
        if(doesContainNOTSuffix(parameters.length, expectedLength, parameters[parameters.length-1])){
            return path -> !(path.getFileName().toString().startsWith(value);
        }
        return path -> (path.getFileName().toString().startsWith(value);
    }

    /**
     * This class implements the suffix filter.
     * @param parameters given command paramaters.
     * @param expectedLength the expected length of the command with a NOT suffix.
     * @return lambda function of the greater_than filter.
     * @throws BadParameterFilterException
     */
    static FileFilter suffixFilter(String[] parameters, int expectedLength) throws
            BadParameterFilterException{
        String value = parameters[0];
        if(doesContainNOTSuffix(parameters.length, expectedLength, parameters[parameters.length-1])){
            return path -> !(path.getFileName().toString().endsWith(value);
        }
        return path -> (path.getFileName().toString().endsWith(value);
    }

They differ only in the String method used in the lambda. I would like to combine them into one, but you can't pass a method as a varible.

Thank you!


Solution

  • Just to combine the two methods shown into one, you can add another BiPredicate<String, String> parameter.

    static FileFilter stringFilter(String[] parameters, int expectedLength, BiPredicate<String, String> stringPredicate) throws
            BadParameterFilterException{
        String value = parameters[0];
        if(doesContainNOTSuffix(parameters.length, expectedLength, parameters[parameters.length-1])){
            return path -> !stringPredicate.test(path.getFileName().toString(), value);
        }
        return path -> stringPredicate.test(path.getFileName().toString(), value);
    }
    

    And pass (x, y) -> x.endsWith(y) and (x, y) -> x.startsWith(y) to it in the two cases respectively.

    As with the file size predicates, you can probably do it with the same approach.