4

Scriptable Java stream() filter

 2 years ago
source link: https://www.bytebang.at/Blog/Scriptable+Java+stream%28%29+filter?language=de
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK