CoupFlu
CoupFlu

Reputation: 321

Creating Predicates on the fly

I have a String[] of user input and I want to filter a Collection of devices based on if the hostName of the device contains any of the user input.

I'm trying to follow the lesson https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html to do this.

interface PredicateOperation{
    Predicate operation(String[] input);
}

public Predicate getPredicate(String[] input, PredicateOperation op){
    return op.operation(input);
}

private TufinDeviceCollection<TufinDevice> filter(TufinDeviceCollection<TufinDevice> devices) {        

       //Check if any HostNames of the devices contain any of the items in String[] modelContains

            devices = devices.stream()
                    .sequential()
                    .filter(//How do i create this predicate?)//we need to create the lamda expression to evaulate if the hostName of device d contains any of the items String[] userInput
                    .collect(Collectors.toCollection(TufinDeviceCollection<TufinDevice>::new));

    }

It is unclear to me how to define the PredicateOperation that goes in .filter(..)

Upvotes: 3

Views: 374

Answers (3)

Andrew
Andrew

Reputation: 49606

.filter(device -> Arrays.stream(userInput)
                        .anyMatch(input -> device.getHostName().contains(input)))

But you need String[] userInput to be accessible from the filter method.

I guess it was an attempt to write own @FunctionalInterface to replace the standard Predicate<T>.

interface PredicateOperation {
    Predicate operation(String[] input);
}

It's not very practical, though.

PredicateOperation operation = (String[] input) -> ((Object o) -> true);

Why would I need to return a Predicate if I can return a result? A little enhanced version would be

interface PredicateOperation {
    boolean operation(String[] input);
}

and

PredicateOperation operation = (String[] input) -> true;

which still isn't particularly useful for Stream API since Stream#filter expects a java.util.function.Predicate<T>, not your type.

And, yes, stop using raw Predicates.

Upvotes: 3

stackFan
stackFan

Reputation: 1608

I prefer to separate predicate on a separate line and apply it later on filter() for readability and re-usability purposes. So the code would be somewhat like :

private TufinDeviceCollection<TufinDevice> filter(TufinDeviceCollection<TufinDevice> devices) {        

   Predicate< ? super TufinDevice> deviceFilter = device -> Arrays.stream(userInput)
                                                 .anyMatch(input -> device.getHostName().contains(input));

   devices = devices.stream()
                .sequential()
                .filter(deviceFilter)
                .collect(Collectors.toCollection(TufinDeviceCollection<TufinDevice>::new));

}

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691765

device -> Stream.of(inputs).anyMatch(input -> device.hostName.contains(input))

Upvotes: 0

Related Questions