jshell and hit the Enter key.Math.sqrt(1764) and hit the Enter key.$1 + 1
$1.$2 and so on.for (int i = 0; i < 10; i++) System.out.println(i * i);IntStream.range(0, 10).map(i -> i * i).toArray()"Hello". and then hit the Tab key.
toU and hit the Tab key again.
toUpperCase method is completed.new Random(), then Shift+Tab, then the V key (unshifted).Duration, then Shift+Tab, then the I key.BigInteger.v and hit Tab. Look at the argument type.10000000000L and the closing parenthesis. Hit Enter..ne and Tab. We want to know what the next prime number is. Pick the most likely method and call it./vars, /methods, /list/list -all, customize with /set start
/help set start shows how/edit, /edit snippet, /set editor /open snippet/env -class-path path, jshell --class-pathList<Integer> piDigits = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9];
Set<Integer> primes = { 2, 7, 31, 127, 8191, 131071, 524287 };List<Integer> piDigits = List.of(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9); Set<Integer> primes = Set.of(2, 7, 31, 127, 8191, 131071, 524287);
List and Set interface.Arrays.asList, but objects are immutable.list1 consisting of the integers 1, 7, 2, 9 with List.of and another one, called list2, with Arrays.asList.Collections.sort.List.of(...) is immutable.Arrays.asList(...)?Map<Integer, String> platonicSolids = { 4 : "tetrahedron", 6 : "cube",
8 : "octahedron", 12 : "dodecahedron", 20 : "icosahedron" };Map<Integer, String> platonicSolids = Map.of(4, "tetrahedron", 6, "cube", 8, "octahedron", 12, "dodecahedron", 20, "icosahedron");or
import static java.util.Map.*; platonicSolids = ofEntries(entry(4, "tetrahedron"), entry(6, "cube"), ...);
What does this code print?
Map<String, Integer> months = Map.of("Jan", 1, "Feb", 2, "Mar", 3, "Apr", 4, "May", 5, "Jun", 6,
"Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12);
System.out.println(map);
{Jan=1, May=5, Aug=8, ..., Feb=2}{Apr=4, Aug=8, Dec=12, ... Sep=9}{Jan=1, Feb=2, Mar=3, ..., Dec=12}of methods implemented?static <E> List<E> of(E... elements)Map<K, V>.ofK V ...Map.of() Map.of(K, V) Map.of(K, V, K, V) ...
Map.ofEntries(Map.Entry ...)List.of(), List.of(E), List.of(E, E), ...name = person.name ?: "John Q. Public";
name = Objects.requireNonNullElse(person.name, "John Q. Public");
name = Objects.requireNonNullElseGet(person.name,
() -> System.getProperty("default.name"));Optional look good:
Optional<String> maybeName = person.name(); // Returns Optional
name = maybeName.orElse("John Q. Public");
Optional RefresherOptional encapsulates “a value or empty”.Optional<String> = stream.filter(s -> s.startsWith("Q")).findFirst();
null...if (maybeName.isPresent()) {
String value = maybeName.get();
}if (person.name != null)
Optional Cheat Sheetdata = opt.orElse(defaultValue); data = opt.orElseGet(() -> ...); data = opt.orElseThrow(SomeException::new); data = opt.orElseThrow(); // same asget, throwsNoSuchElementException, Java 10
opt.ifPresent(value -> ...); opt.ifPresentOrElse(value -> ..., () -> ...); // Java 9
anotherOpt = opt.filter(value -> ...).map(value -> ...).or(() -> ...);
The call Runtime.version().build() returns an Optional<Integer>, the build number of the JDK. Given the declaration
Optional<Integer> build = Runtime.version().build();
which of the following code segments print the build number or "unknown" if the build number isn't present?
build.ifPresentOrElse(System.out::println, "unknown");System.out.println(build.orElse("unknown"));System.out.println(build.get() == null ? "unknown" : build.get());Optional Code SmellsOptional should never be null!Optional type.
null is manageable inside a class.Optional
Optional intended as return type.List of Optional values or a Map with Optional keys is dubious.
List<Optional<String>>, just have List<String>Optional to make a null check:
Optional.ofNullable(result).ifPresentOrElse(...); // Way too complex
Optional Java 9 NewsHttpClient.authenticator/cookieManager/proxy/sslParameters, ServiceLoader.findFirst, Runtime.Version.build/pre/post, ProcessHandle.of, ProcessHandle.Info.command/commandLine/arguments/startInstant/totalCpuDuration/userOptional<T> or(Supplier<? extends Optional<? extends T>> supplier)
maybeName = maybeName.or(() ->
Optional.of("John Q. Public")); // Another Optional
maybeName nonempty? If so, or returns it.Optional maybeName.ifPresentOrElse(System.out::println, // Consumer () -> logger.warning(...)); // Runnable
Optional Java 9 NewsStream<T> stream()Yields a stream of length 0 or 1.
Stream.flatMap to drop empty results:
Stream<String> users = people.map(Person::name) .flatMap(Optional::stream);
Consider the method
public Optional<String> input(String prompt) {
return Optional.ofNullable(JOptionPane.showInputDialog(prompt));
}
The method gets an input string or an empty Optional if the input was canceled by the user.
input("How old are you?") and convert the result to an Optional<Integer> that is empty if the user provided no input or the string wasn't an integer.Don't use the isPresent or get methods. Try not to use ifPresent either.
input("How old are you?").
filter(s -> s.matches("[0-9]+")).
map(Integer::parseInt)
input("How old are you?").
or(() -> input("Don't be shy! How old?")).
filter(s -> s.matches("[0-9]+")).
map(Integer::parseInt)
// Note delayed execution of the second input
collection.stream() // Stream creation
.filter(s -> s.length() > 10) // Intermediate operations
.map(String::toUpperCase)
.collect(Collectors.joining("\n")) // Terminal operationMap<Integer, Set<String>> stringsByLength = collection.stream()
.collect(Collectors.groupingBy(String::length,
Collectors.toSet()))
Scanner.tokens, Matcher.results, ServiceLoader.stream, LocalDate.datesUntil, StackWalker.walk, ClassLoader.resources, Process.children/descendants, Catalog.catalogs, DriverManager.driversFiles.lines now uses a memory mapped file.
takeWhile, dropWhileBigInteger limit = new BigInteger("10000000");
Stream<BigInteger> integers
= Stream.iterate(BigInteger.ZERO,
n -> n.compareTo(limit) < 0,
n -> n.add(BigInteger.ONE));double time(Callable<?> task) throws Exception {
long start = System.nanoTime();
System.out.println(task.call());
long end = System.nanoTime();
return (end - start) * 1.0E-9;
}
Path path = Paths.get("/home/cay/Dropbox/presentations/2018/corejava9/gutenberg/crsto10.txt")
time(() -> Files.lines(path).filter(w -> w.matches(".*[Cc]ount.*")).count())
In JShell, do this:
import java.time.*; LocalDate from = LocalDate.of(2000, 1, 1); LocalDate to = LocalDate.of(3190, 7, 4);
Here is how you can work with these objects:
to.getDayOfMonth() from.getDayOfWeek() == DayOfWeek.SATURDAY
Now make a stream of dates by calling:
from.datesUntil(to)
and find out how many of them are a “Friday the 13th”.
Hint: filter, count
What did you get?
from.datesUntil(to). filter(d -> d.getDayOfWeek() == DayOfWeek.FRIDAY). filter(d -> d.getDayOfMonth() == 13). count()
flatMapping, filtering:
import static java.util.stream.Collectors.*;
Map<String, Set<String>> longWordsByFirstLetter =
Files.lines(Paths.get("/usr/share/dict/words")).
collect(
groupingBy(w -> w.substring(0, 1),
filtering(w -> w.length() > 15,
toSet())));
words.filter(...).collect(...)? Now let's look at another question about words. Given a particular last letter, what characters can be in such a word? For example, looking at all words ending with v, not a single one contains the letters j, q, w, or x.
/usr/share/dict/words. public Stream<String> letters(String w) { return Stream.of(w.split("")); }
flatMapping to flatten those streams in the same group.public Stream<String> letters(String w) { return Stream.of(w.split("")); }
import java.util.stream.Collectors.*;
Path path = Paths.get("/usr/share/dict/words");
Map<String, Set<String>> result = Files.lines(path).
collect(
groupingBy(w -> w.substring(w.length() - 1),
flatMapping(w -> letters(w),
toSet())))
byte[] bytes = url.openStream().readAllBytes();There is also
readNBytes.InputStream.transferTo(OutputStream) transfers all bytes from an input stream to an output stream.Reader.transferTo(Writer)Scanner.tokens gets a stream of tokens, similar to Pattern.splitAsStream from Java 8:
Stream<String> tokens = new Scanner(path).useDelimiter("\\s*,\\s*").tokens(); PrintWriter, Scanner, etc. can be specified as Charset instead of String:
new Scanner(path, StandardCharsets.UTF_8)
In JShell, start with
import java.net.*;
import static java.nio.charset.StandardCharsets.*;
URL url = new URL("http://www.gutenberg.org/files/11/11-0.txt");
InputStream in = url.openStream();
Now we want to read the contents of this web page as a string.
There is no method (yet) for reading a string from a given input stream. So, read it into a byte array, and then convert it to a string, using the constructor
String(byte[] bytes, Charset encoding)
What is the length of the string that you get? Use StandardCharsets.UTF_8 as the encoding.
How many times does it contain “Alice”? (Hint: Scanner.tokens)
Pattern class describes regex: Pattern pattern = Pattern.compile("[0-9]([0-9,]*[0-9])?");Matcher does the actual matching:
Matcher matcher = pattern.matcher(inputString);
matcher.matches() to see if the entire input string matches.matcher.find() to find matches within the input string.MatchResult:
MatchResult result = matcher.toMatchResult(); int start = result.start();
([1-9]|1[0-2]):([0-5][0-9])(?<suffix>[ap]m)
String hours = result.group(1);
String suffix = result.group("suffix");result.group() yields the entire match.Matcher.stream and Scanner.findAll gets a stream of match results:
Pattern pattern = Pattern.compile("[^,]");
Stream<String> matches = pattern.matcher(str).results().map(MatchResult::group);
matches = new Scanner(path).findAll(pattern).map(MatchResult::group);Matcher.replaceFirst/replaceAll now have a version with a replacement function: String result = Pattern.compile("\\pL{4,}")
.matcher("Mary had a little lamb")
.replaceAll(m -> m.group().toUpperCase());
// Yields "MARY had a LITTLE LAMB"
As before, read the contents of “Alice in Wonderland” into a string:
import java.net.*;
import static java.nio.charset.StandardCharsets.*;
URL url = new URL("http://www.gutenberg.org/files/11/11-0.txt");
String text = new String(url.openStream().readAllBytes(), UTF_8);
Using the regular expression [0-9]+ and one of the new Java 9 features, and match all integers.
How many are there?
How do you replace them all with their hexadecimal value?
Pattern.compile("[0-9]+").matcher(text).results().count()
Pattern.compile("[0-9]+").matcher(text).results().map(MatchResult::group).toArray()
Pattern.compile("[0-9]+").matcher(text).replaceAll(m ->
String.format("0x%x", Integer.parseInt(m.group())))
CompletableFuture RefresherCompletableFuture<String> f = CompletableFuture.supplyAsync(
() -> readPage(url), executor);
f.whenComplete((s, t) ->
{
if (t == null) Process the result s
else Process the exception t
});CompletableFuture.completedFuture(urlToProcess)
.thenComposeAsync(this::readPage, executor)
.thenApply(this::getImageURLs)
.thenCompose(this::getImages)
.thenAccept(this::saveImages);
CompletableFuture.completedFuture(urlToProcess)
.thenComposeAsync(this::readPage, executor)
.completeOnTimeout("<html></html>", 30, TimeUnit.SECONDS)
.thenApply(this::getImageURLs)
...
CompletableFuture.completedFuture(urlToProcess)
.thenComposeAsync(this::readPage, executor)
.orTimeout(30, TimeUnit.SECONDS)
.thenApply(this::getImageURLs)
...
ProcessBuilder to set process parameters:
Process proc = new ProcessBuilder("gcc", "myapp.c") // command and args
.directory(path.toFile()) // Working directory
.redirectError(errorFile)
.start();Writer out = new OutputStreamWriter(proc.getOutputStream()); out.write(...); out.close();
try (Scanner in = new Scanner(proc.getInputStream())) {
while (in.hasNextLine())
System.out.println(in.nextLine());
}int exitCode = process.waitFor();
ProcessHandle as:
proc.toHandle() from a Process procProcessHandle.of(pid) from an OS PIDProcessHandle.current()ProcessHandle.allProcesses()long pid = handle.pid(); Optional<ProcessHandle> parent = handle.parent(); Stream<ProcessHandle> children = handle.children(); Stream<ProcessHandle> descendants = handle.descendants(); ProcessHandle.Info info = handle.info();
ProcessHandle.info yields command/commandLine/arguments/startInstant/totalCpuDuration/user if available.List all Java processes that are currently running.
ProcessHandle.allProcesses().
flatMap(h -> h.info().command().stream()).
filter(c -> c.contains("java")).
toArray()
ProcessHandle.allProcesses().
filter(h -> h.info().command().map(c -> c.contains("java")).orElse(false)).
map(ProcessHandle::pid).toArray()
onExit method yields a CompletableFuture<ProcessHandle> that completes when the process is completed:
Process process = new ProcessBuilder("/bin/ls").start();
process.onExit().thenAccept(h -> System.out.println(h + " all done"));
Crazy calculator with jshell:
String expr = "6 * 7";
Process proc = new ProcessBuilder("jshell", "-q").start();
Writer out = new OutputStreamWriter(proc.getOutputStream());
out.write("System.out.println(" + expr + ");\n");
out.close();
String result = new String(proc.getInputStream().readAllBytes(), "UTF-8");
It's unsatisfactory that some cleanup is required.
Let's do something crazier instead. Can we call System.exit(expr) instead and retrieve the exit value in the onExit method?
In Java 9, this works if you change the JShell command slightly. Run
jshell --execution local
Otherwise JShell won't exit when the System.exit method is called.
In Java 10, don't call System.exit, but instead use /exit followed by the expression to be evaluated.
String expr = "6 * 7";
Process proc = new ProcessBuilder("jshell", "-q").start();
proc.onExit().thenAccept(h -> System.out.println(h.exitValue()));
Writer out = new OutputStreamWriter(proc.getOutputStream());
out.write("/exit " + expr + "\n");
out.close();
URLConnection/HttpURLConnectionjdk.incubator module
--add-modules jdk.incubator.httpclientHttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://horstmann.com"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
client.sendAsync(request, HttpResponse.BodyHandler.asString())
.completeOnTimeout("<html></html>", 10, TimeUnit.SECONDS)
.thenAccept(response -> Process response.body());
jshell --add-modules jdk.incubator.httpclient
import jdk.incubator.http.*;
import java.net.*;
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder().
uri(URI.create("http://www.gutenberg.org/files/11/11-0.txt")).
GET().
build();
client.sendAsync(request, HttpResponse.BodyHandler.asString()).
thenAccept(response -> System.out.println(response.body()));
@Deprecated has since and forRemoval attributes.java.util classes Observable, Observer (but not Vector, Hashtable).Object.finalize and Runtime.runFinalizersOnExit methods.Class.newInstance
Constructor.newInstance which wraps them in an InvocationTargetExceptionjava.activation, java.corba, java.transaction,
java.xml.bind, java.xml.wsjdeprscan to get deprecated uses in your code.Here is a class Fred whose no-arg constructor throws an IOException:
class Fred {
public Fred() throws IOException {
throw new IOException("No Fred.properties");
}
}
Can this method throw an IOException? Why or why not?
public Fred haveFred() throws ReflectiveOperationException {
return Fred.class.newInstance();
}
Call the method. What happens?
Now try:
public Fred haveFred() throws ReflectiveOperationException {
return Fred.class.getConstructor().newInstance();
}
What is different?
_ is not a valid variable name.try-with-resources can be used with an effectively final variable:
void print(PrintWriter out, String[] lines) {
try (out) { // Effectively final variable
for (String line : lines)
out.println(line.toLowerCase());
}
}private and private static methods.file.preferences=Pr\u00e9f\u00e9rencesjavac creates output directories, specified with the -d, -s, -h options, if they do not already exist.BigInteger.TWOWrite a utility method:
String string(InputStream in, Charset cs) throws IOException
Your method should read the contents of in as a string. Be sure to close the string even if an exception occurs.
What exception could occur?
String string(InputStream in, Charset cs) throws IOException {
try (in) {
return new String(in.readAllBytes(), cs);
}
}
InputStream makeUnhappy(InputStream in, int b) {
return new InputStream() {
public int read() throws IOException {
int r = in.read();
if (r == b) throw new IOException();
return r;
}
public void close() throws IOException {
System.out.println("Closing stream.");
in.close();
}
};
}
string(makeUnhappy(Files.newInputStream(Paths.get("/usr/share/dict/words")), '*'), UTF_8)
string(makeUnhappy(new URL("http://www.gutenberg.org/files/11/11-0.txt").openStream(), '*'), UTF_8)

var instead of type for local variables:
var counter = 0; // anintvar message = "Greetings, earthlings!"; // aString
counter = 0.5; // Error—can't assign a double to an int
var traces = Thread.getAllStackTraces(); // a Map<Thread,StackTraceElement[]> System.getProperty("java.version") returns "9.0.1", not "1.9.0"javac -release 8 compiles for Java 8.
-source, -target, -bootclasspathA.class
B.class
C.class
META-INF
├─ MANIFEST.MF (with line Multi-Release: true)
├─ versions
├─ 9
│ ├─ A.class
│ └─ B.class
└─ 10
└─ B.class
ls
-h) and long double-dash options (ls --human-readable).java -classpath).jar which has archaic TAR options (jar cvf).-?, -help,
--help --example-option value
--example-option=value
-e value
-evalue-ef is the same as -e -f--module-path or
-p--class-path or
-cp-classpath still works for backward compatibility.Try out those cleaned-up arguments. Which of these works?
java --jar MyApp.jarjar -c -f=MyApp.jar *.classjar -cv -f MyApp.jar *.classjar cvf MyApp.jar *.classjava --jar MyApp.jarjava -jarjar -c -f=MyApp.jar *.class-f=MyApp.jarjar -cv -f MyApp.jar *.class-f: File or directory not found.jar cvf MyApp.jar *.classjar -cvf MyApp.jar *.class also works.@SafeVarargs on private methods:
@SafeVarargs private <T> void process(T... values)
static and final methods and constructorsList<String> alwaysJava = new ArrayList<>()
{
public String get(int n) { return "Java"; }
};
Look at this method:
private <T> T[] asArray(T... args) { return args; }
Now try this:
Optional<Integer>[] optInts = asArray(Optional.of(42), Optional.empty());
Object[] objects = optInts;
objects[0] = Optional.of("Java");
System.out.println(optInts[0].get() + 1);
This can't be good. objects[0] and optInts[0] are the same object.
Where does an exception occur?
Annotate asArray with @SafeVarargs. Does that solve the problem?
Is this method safe?
@SafeVarargs private <T> void printAll(T... args) {
Stream.of(args).forEach(System.out::println);
}

CompletableFuture