Java - Pattern matching and virtual threads in Java 19 preview

2 minute read

Java 19 preview improved the pattern matching language feature. The following code shows how we can leverage them with virtual threads.

Full code can be found from the github

The demo code is trying to find the quickest website on landing page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package org.demo;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Stream;

/**
 * Date ${DATE}
 *
 * @author Nam Seob Seo
 */

public class Main {

    sealed interface IResult<T> {
        record Success<T>(T data) implements IResult<T> {}
        record Failed<T>(Exception exception) implements IResult<T> {}
    }

    record URLData(URL url, byte[] response, long durationMs) { }

    IResult<URLData> fromFuture(Future<IResult<URLData>> future) {
        try {
            IResult<URLData> result = future.get();
            return switch(result) {
                case IResult.Success<URLData> s -> s;
                case IResult.Failed<URLData> f -> {
                    System.out.println("failed: %s".formatted(f.exception.getMessage()));
                    yield f;
                }
            };
        } catch (InterruptedException | ExecutionException e) {
            return new IResult.Failed<>(e);
        }
    }

    IResult<URLData> fetchUrlData(URL url) {
        try (InputStream in = url.openStream()) {
            try {
                Instant start = Instant.now();
                System.out.println("started: %s".formatted(url.toString()));
                var bytes = in.readAllBytes();
                var duration = Duration.between(start, Instant.now()).toMillis();
                System.out.println("finished: %s(%dms)".formatted(url.toString(), duration));
                return new IResult.Success<>(new URLData(url, bytes, duration));
            } catch (Exception e) {
                return new IResult.Failed<>(e);
            }
        } catch (IOException e) {
            return new IResult.Failed<>(e);
        }
    }
    List<URLData> retrieveURLs(List<URL> urls) {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            var tasks = urls
                    .stream()
                    .map(url -> executor.submit(() -> fetchUrlData(url)))
                    .toList();
            System.out.println("%d tasks have been created".formatted(tasks.size()));
            return tasks.stream().map(this::fromFuture)
                    .map(s -> s instanceof IResult.Success<URLData>(URLData d) ? d : null)
                    .filter(Objects::nonNull)
                    .toList();
        }
    }

    static String toJson(List<URLData> result) {
        var list = result.stream()
                .sorted(Comparator.comparingLong(x -> x.durationMs))
                .map(data ->
                        """
                        {
                            "url": "%s",
                            "duration:: "%d(ms)",
                            "size": "%d(KB)"
                        }""".formatted(data.url, data.durationMs, data.response.length / 1024))
                .toList();

        return """
                 [
                   %s
                 ]""".formatted(String.join(",", list));
    }

    public static void main(String[] args) {
        List<URL> urls = Stream.of(
                    "https://www.google.com",
                        "https://www.youtube.com",
                        "https://www.yahoo.com",
                        "https://www.github.com",
                        "https://www.linkedin.com",
                        "https://www.amazon.com",
                        "https://www.bing.com",
                        "https://www.reddit.com",
                        "https://www.mozilla.org",
                        "https://www.facebook.com",
                        "https://www.ebay.com",
                        "https://www.twitter.com",
                        "https://www.cloudflare.com",
                        "https://www.datadoghq.com")
                .map(url -> {
                    try {
                        return new URL(url);
                    } catch (MalformedURLException e) {
                        throw new RuntimeException(e);
                    }
                }).toList();

        List<URLData> result = new Main().retrieveURLs(urls);
        System.out.println(toJson(result));
    }
}

Categories:

Updated: