Friday, 4 April 2014

Lambdas make things better pt1.

Lambdas in Java make a lot of code much prettier.

Take this quick example. Without lambdas, it's not worth the effort. With lambdas, it's pretty enough to do:

public class EndpointConnection<T> {

    public static class ConnectionConfig {
        public int maxRetries;
        public int retryDelay;
    }

    private final T endpoint;

    private final int maxRetries;
    private final int retryDelay;

    public EndpointConnection(final T endpoint, final ConnectionConfig config) {
        this.endpoint = expect(endpoint);
        this.maxRetries = expect(config.maxRetries);
        this.retryDelay = expect(config.retryDelay);
    }

    public <R> R attempt(Function<T> fn) {

        int count = 1;
        R result = null;
        while (result == null) {

            if (count >= this.maxRetries) throw new RuntimeException("Error: max# of attempts exceeded.");

            result = lambda.apply(this.endpoint);

            if (result == null) {

                count++;

                try {
                    Thread.currentThread().sleep(this.retryDelay * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }

        return result;
    }

}

Then combine with the factory method in the class in question:

public class Endpoint {

    ...

    public EndpointConnection<BridgeEndpoint> newConnection(final ConnectionConfig config) {
        return new EndpointConnection<>(this,config);
    }

}

and call like so:

return endpointConnection.attempt(Endpoint::someFunctionCall);

This is merely an example for the purposes of illustration however, I don't recommend using this sort of code when you can use something like this instead:

https://github.com/rholder/guava-retrying

Scan for a set of URLS with Jsoup.

Snippet to load a list of urls, scan them for link tags, and output them as a file - with Jsoup.


public void run(final String in, final String out, final String match) throws IOException {

        final StringJoiner joiner = new StringJoiner("\n");

        try (BufferedReader br = new BufferedReader(new FileReader(in))) {
            for (String line; (line = br.readLine()) != null; ) {
                try {
                    System.out.println("Scanning: "+line);
                    for (final Element link : Jsoup.connect(line)
                           .timeout(0)
                           .get()
                           .select(match)) {
                        joiner.add(link.attr("href"));
                    }
                } catch (Exception e) {
                    System.err.println("Error: " + e.getMessage());
                }
            }
        }

        Files.write(Paths.get(out), joiner.toString().getBytes());

    }

Where the 'match' arg will be a Jsoup matching pattern such as: a[href^=http://].