Java 9新特性深度探索:JShell实战与API详解

本文详细记录了在新加坡Java用户组的演讲内容,聚焦Java 9中未被广泛了解的API特性。通过JShell实时演示了集合、Stream、CompletableFuture、StackWalker等核心API的更新,包含大量实际代码示例和HTTP/2客户端等新功能探索。

新加坡Java用户组演讲记录

衷心感谢新加坡Java用户组邀请我作为2018年首场活动的演讲嘉宾,感谢Pivotal提供场地和餐饮支持,也感谢所有抽出时间参与的听众们给予的积极反馈和精彩提问!

尽管活动在新年伊始举行,但参与人数众多,整体氛围非常愉快。本次演讲题为《Java 9,第二集》,顾名思义是对几周前该用户组举办的另一场Java 9活动的后续跟进。因此,我选择深入探讨一些在上次活动中未涉及、较小众且不太为人知的Java 9 API。在大约一小时内,我们使用JShell探索了Collections、Stream、CompletableFuture、Stackwalker、Process、HTTP/2客户端和JShell API的更新。这是一场节奏明快、包含大量示例的实时演示环节。

新加坡Java用户组拥有优秀的组织团队。所有安排都井井有条,演讲的高质量录制视频也立即在线发布。如果您未能亲临现场,欢迎在此观看会议录像:

[视频链接]

一如既往,幻灯片可在线上获取(点击下载): Java 9, Episode 2 - 来自 Miro Cupak

如果您想亲自尝试这些示例,请随意使用我的JShell会话历史:

  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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
1+1

int x = 1+1

System.out.println(x)

Thread.sleep(2000)

/vars

/types

/list

/l

/help

Set<String> set = new HashSet<String>()

set.add("a")

set.add("b")

set.add("c")

Collections.unmodifiableSet(set)

List<Integer> list = List.of(1,2,3)

list.add(4)

list.getClass()

Map.ofEntries(entry(1, "hello"))

IntStream.range(0, 10).forEach(System.out::println)

IntStream.range(0, 10).limit(5).forEach(System.out::println)

IntStream.range(0, 10).skip(5).forEach(System.out::println)

IntStream.range(0, 10).takeWhile(i -> i<5).forEach(System.out::println)

IntStream.range(0, 10).dropWhile(i -> i<5).forEach(System.out::println)

IntStream.iterate(0, i -> i+2).filter(j -> j<100).forEach(System.out::println)

IntStream.iterate(0, i -> i<100, i -> i+2).forEach(System.out::println)

Stream.of(1)

Stream.of(null)

Stream.ofNullable(null)

Stream.ofNullable(null).count()

List<Integer> list = List.of(2,3,4,7,9,11)

list.stream().filter(i -> i >5).collect(Collectors.groupingBy(j -> j %2, Collectors.counting()))

list.stream().filter(i -> i >5).collect(Collectors.groupingBy(j -> j %2, Collectors.counting()))

list.stream().collect(Collectors.groupingBy(j -> j %2, Collectors.filtering(i -> i>5, Collectors.counting())))

Stream.of(entry(1, Set.of("a", "b")),entry(1, Set.of("a", "c")),entry(2, Set.of("d")))

Stream<Map.Entry<Integer,Set<String>>> entries = Stream.of(entry(1, Set.of("a", "b")),entry(1, Set.of("a", "c")),entry(2, Set.of("d")))

entries.collect(Collectors.groupingBy(e -> e.getKey(), Collectors.mapping(e -> e.getValue(), Collectors.toSet())))

entries.collect(Collectors.groupingBy(e -> e.getKey(), Collectors.flatMapping(e -> e.getValue().stream(), Collectors.toSet())))

Stream<Map.Entry<Integer,Set<String>>> entries = Stream.of(entry(1, Set.of("a", "b")),entry(1, Set.of("a", "c")),entry(2, Set.of("d")))

entries.collect(Collectors.groupingBy(e -> e.getKey(), Collectors.flatMapping(e -> e.getValue().stream(), Collectors.toSet())))

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.complete("done")

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.get()

cf.completeExceptionally(new IllegalStateException())

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.completeOnTimeout("timed out", 5, TimeUnit.SECONDS)

cf

cf

cf

cf

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

cf.orTimeout(5, TimeUnit.SECONDS)

cf

cf

cf

cf

cf

cf

cf

cf.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

CompletableFuture<String> copy = cf.copy()

cf

copy

cf.complete("done")

cf

copy

copy.get()

CompletableFuture<String> cf = new CompletableFuture<String>()

CompletableFuture<String> copy = cf.copy()

copy.complete("done")

copy

cf

StackTraceElement[] sst = new Throwable().getStackTrace()

StackTraceElement[] st = new Throwable().getStackTrace()

st

StackWalker.getInstance().walk(s -> s.collect(Collectors.toList()))

StackWalker.getInstance().walk(s -> s.limit(3).collect(Collectors.toList()))

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.collect(Collectors.toList()))

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.map(f -> f.getDeclaringClass()).collect(Collectors.toList()))

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(s -> s.map(f -> f.getDeclaringClass()).filter(c -> c.equals(jdk.jshell.execution.Util.class)).collect(Collectors.toList()))

new ProcessBuilder().command("jps").start()

ProcessHandle.current().pid()

ProcessHandle.current().info()

ProcessHandle.current().info().commandLine()

ProcessHandle.allProcesses().map(p -> p.info().command()).forEach(System.out::println)

ProcessHandle.allProcesses().map(p -> p.info().command()).collect(Collectors.toList())

new ProcessBuilder().command("sleep", "3").start().toHandle().onExit().thenAccept(System.out::println)

ProcessBuilder jps = new ProcessBuilder().command("jps")

ProcessBuilder grep = new ProcessBuilder().command("grep", "JShell")

List<Process> pipeline = ProcessBuilder.startPipeline(List.of(jps, grep))

pipeline

new BufferedReader(new InputStreamReader(pipeline.get(1).getInputStream())).readLine()

HttpHandler handler = he -> {
    String body = "hello singapore";
    he.sendResponseHeaders(200, body.length());
    try (OutputStream os = he.getResponseBody()) {
        os.write(body.getBytes());
    }
}

/l

HttpServer hs = HttpServer.create(new InetSocketAddress(8000), 0)

hs.createContext("/hello", handler)

hs.start()

URI uri = new URI("http://localhost:8000/hello")

HttpURLConnection c = (HttpURLConnection) uri.toURL().openConnection()

c.setRequestMethod("GET")

c.getResponseCode()

new BufferedReader(new InputStreamReader(c.getInputStream())).readLine()

HttpClient client = HttpClient.newHttpClient()

HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build()

HttpResponse<String> response = client.send(request, BodyHandler.asString())

response.statusCode()

response.body()

CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, BodyHandler.asString())

CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, BodyHandler.asString())

response.get().body()

JShell js = JShell.create()

List<SnippetEvent> events = js.eval("1+1")

js.variables()

js.variables().forEach(System.out::println)

events.stream().map(e -> e.status()).forEach(System.out::println)

events.stream().map(e -> e.snippet().source()).forEach(System.out::println)

events.stream().map(e -> e.value()).forEach(System.out::println)

/save -history singajug.jsh
1
2
singajug.jsh
hosted with ❤ by GitHub
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计