Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Dynamically Invoke Functions

Tags:

lambda

java-8

I've been searching around the web for an example to this questions, but I haven't had any luck so far. I would like to use a Builder, but instead of with objects have the builder "build" a more complex function that uses helper functions.

For example, let's say that I have a class that gets a list of strings from some source (for simplicity I added them manually). Then once I've gathered the strings I would like to optionally apply functions on those strings. The class below is really pseudo-coded, but I think it encapsulates the behavior that I'm going for:

public class StringGetter {

    private List<Function<String, String>> listOfFunctions;

    public List<String> getListOfStrings() {
       List<String> strings = new ArrayList<String>();
       strings.add(" test1");
       strings.add("test2    ");

       listOfFunctions.forEach((function) ->
           // apply function on strings
       )

        return strings;
    }

    public StringGetter withCapitalLetters() {
       listOfFunctions.add(String::toUppserCase);
       return this;
    }

    public StringGetter withTrimmed() {
       listOfFunctions.add(String::trim);
       return this;
    }

    public StringGetter withSingleQuotes() {
       listOfFunctions.add(s -> ' + s + ');
       return this;
    }
}

How could I make it so I could put whatever helper methods that I wanted:

StringGetter sg = new StringGetter();

List<String> capitalAndTrimmed = sg.getListOfStrings()
                                        .withCapitalLetters()
                                        .withTrimmed();
System.out.println(capitalAndTrimmed);
Output: ["TEST1", "TEST2"]



List<String> capital = sg.getListOfStrings()
                             .withCapitalLetters()
System.out.println(capital);
Output: [" TEST1", "TEST2   "]



List<String> singleQuotes = sg.getListOfStrings()
                                  .withSingleQuotes();
System.out.println(singleQuotes);
Output: ["' test1'", "'test2    '"]
like image 306
Zachary Hamm Avatar asked May 03 '26 20:05

Zachary Hamm


1 Answers

Well you could do something like this:

static public class StringGetter {

    private List<Function<String, String>> listOfFunctions = new ArrayList<>();


    public StringGetter withCapitalLetters() {
        listOfFunctions.add(String::toUpperCase);
        return this;
    }

    public StringGetter withTrimmed() {
        listOfFunctions.add(String::trim);
        return this;
    }

    public StringGetter withSingleQuotes() {
        listOfFunctions.add(s -> "'" + s + "'");
        return this;
    }

    public List<String> apply(List<String> input) {
        Function<String, String> one = listOfFunctions.stream()
                .reduce((left, right) -> left.andThen(right))
                .orElse(Function.identity());

        return input.stream().map(one::apply).collect(Collectors.toList());

    }
}

And usage along the lines of:

 StringGetter sg = new StringGetter();

 sg.withCapitalLetters().withTrimmed();
 System.out.println(sg.apply(List.of("test")));

I would change it your implementation to:

Function<String, String> first = Function.identity();

public StringGetter withCapitalLetters() {
   // may be do a check here so that this is not called twice
   first.andThen(String::toUpperCase);
   return this;
} 

.... other methods

public List<String> apply(List<String> input) {
    return input.stream().map(first::apply).collect(Collectors.toList());
}
like image 132
Eugene Avatar answered May 06 '26 14:05

Eugene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!