Willkommen bei bytebang » The blog about all and nothing » Scriptable Java stream() filter

Scriptable Java stream() filter

Dez 31 2019

The Problem

Java 8 introduces the java.util.stream.Stream<T> interface which enables users to perform very efficient operations on arrays and collections. This is a very convenient way how to things very effective and also very elegant.

However - I wondered if it is possible to create a filter which is able to filter objects based on a javascript snippet. Since I could not find an appropriate solution I came up with my own.

The Solution

Beside the fact that my solution is for sure not the most performant one, probably not really suited to process parallel streams and also in terms of security a little bit questionable I decided to publish it on my repository on GitHub. Maybe someone finds it coll and improves it a little bit.

Here is how to use it:

// Read the file
try (Stream<String> stream = Files.lines(Paths.get("/etc/passwd")))
{
       // Instantiate the filter
       NashornFilter scriptfilter = new NashornFilter("o.userid.match('g') != null || o.uid > 1000")
                               .withScriptVariableName("o").onErrorDefaultTo(true);


       // Yeah - Java8 read, filter and instantiate on one line of code !
       ArrayList<PwdUser> users =  stream.map(PwdUser::new)
                                   .filter(scriptfilter::apply)
                                   .sorted((a,b) -> a.userid.compareTo(b.userid))
                                   .collect(Collectors.toCollection(ArrayList::new));

       // And print them
       users.stream().forEach(System.out::println);
}
catch (IOException e)
{
        e.printStackTrace();
}

The magic happens in the NashornFilter class. It can be instantiated using the builder pattern. The script (which is given directly in the constructor) must evaluate to a boolean value.

Internally the Filter instantiates one instance of the nashorn scripting engine (which is deprecated with Java 11) and feeds the objecs from the apply() method to it. The result can either be true, false or an error. In case of an error the user has the choice to decide if errors should be ignored (and a default value should be used) or if an Exception should be thrown.

Happy coding


Get Social


(c) 2024, by bytebang e.U. - Impressum - Datenschutz / Nutzungsbedingungen
-