We continue the story about the APIs that appeared in new versions of Java.
1. Files.mismatch()
Appeared in: Java 12
In practice, it is often necessary to check whether two files are exactly the same or not. Using the method Files.mismatch()
introduced in Java 12, this can finally be done. This method returns the position of the first mismatch byte in two files, or -1
if the files are identical.
This can be useful, for example, when you synchronize the contents of two directories. In order not to overwrite the file when copying with the same contents and not load the disk once again, you can first check whether the files are identical or not:
public static void syncDirs(Path srcDir, Path dstDir)
throws IOException {
try (Stream<Path> stream = Files.list(srcDir)) {
for (Path src : stream.collect(toList())) {
Path dst = dstDir.resolve(src.getFileName());
if (!Files.exists(dst)) {
System.out.println("Copying file " + dst);
Files.copy(src, dst);
} else if (Files.mismatch(src, dst) >= 0) {
System.out.println("Overwriting file " + dst);
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
}
}
}
}
(By the way, when will they finally Stream
inherit from Iterable
? I just want to write for (Path file : stream)
, and not mess around with the intermediate lists.)
2. New methods in java.time
Introduced in: Java 9
For almost 20 years, Java has not had a normal API for working with dates and times. This problem was only solved in Java 8 when they introduced a new package java.time
under the guidance of the notorious Stephen Colborn , creator of the Joda Time library . And in the ninth version java.time
, many interesting methods were added.
Java 8 Duration
(, 2 , 7 , 15 , 12 ). Java 9 toDaysPart()
, toHoursPart()
, toMinutesPart()
, toSecondsPart()
.. :
public static String modifiedAgo(Path path) throws IOException {
FileTime time = Files.getLastModifiedTime(path);
Instant to = Instant.now();
Instant from = time.toInstant();
Duration d = Duration.between(from, to);
return String.format(
" %d , %d , %d , %d ",
d.toDaysPart(), d.toHoursPart(),
d.toMinutesPart(), d.toSecondsPart());
}
, ? Java 8, , . Java 9 Duration.dividedBy()
:
public static long modifiedAgo(Path path, ChronoUnit unit)
throws IOException {
FileTime time = Files.getLastModifiedTime(path);
Instant to = Instant.now();
Instant from = time.toInstant();
Duration d = Duration.between(from, to);
return d.dividedBy(unit.getDuration());
}
public static void main(String[] args) throws Exception {
Path path = ...
System.out.printf(" %d %n",
modifiedAgo(path, ChronoUnit.MONTHS));
}
LocalDate
. LocalDate.ofInstant()
Instant
LocalDate
:
LocalDate date = LocalDate.ofInstant(
Instant.now(), ZoneId.systemDefault());
System.out.println(date);
LocalDate.datesUntil()
, - Stream
:
LocalDate from = LocalDate.of(2020, 1, 1);
LocalDate to = LocalDate.of(2020, 1, 9);
from.datesUntil(to)
.forEach(System.out::println);
:
2020-01-01
2020-01-02
2020-01-03
2020-01-04
2020-01-05
2020-01-06
2020-01-07
2020-01-08
, :
LocalDate from = LocalDate.of(2020, 1, 1);
LocalDate to = LocalDate.of(2020, 1, 31);
from.datesUntil(to, Period.ofWeeks(1))
.forEach(System.out::println);
:
2020-01-01
2020-01-08
2020-01-15
2020-01-22
2020-01-29
:
3. Collection.toArray()
-
: Java 11
Java . Collection
Java 1.2 :
, ( String[]
), :
collection.toArray(new String[0])
. , , , .collection.toArray(new String[collection.size()])
. , , . .
, , IntelliJ IDEA , , .
2016 , , -: - ( JDK 6+). , IDEA , : (default), Java.
, «». Stream.toArray(IntFunction[])
collection.stream().toArray(String[]::new)
. ? , .
Oracle : , ? Java 11 Collection.toArray(IntFunction[])
, .
. , 4 , , :
List<Integer> list = ...;
Integer[] array = list.toArray(Integer[]::new);
4. InputStream
: readNBytes()
, readAllBytes()
, transferTo()
: Java 9 / Java 11
, Java – InputStream
. , Java 8 : , , , , , .. , .
Java 9 InputStream.readAllBytes()
, . , stdout
/stderr
:
Process proc = Runtime.getRuntime().exec("java -version");
try (InputStream inputStream = proc.getErrorStream()) {
byte[] bytes = inputStream.readAllBytes();
System.out.print(new String(bytes));
}
:
openjdk version "14-ea" 2020-03-17
OpenJDK Runtime Environment (build 14-ea+33-1439)
OpenJDK 64-Bit Server VM (build 14-ea+33-1439, mixed mode, sharing)
N
, Java 11 InputStream.readNBytes()
.
( ) InputStream
OutputStream
, InputStream.transferTo()
. , Java :
Process proc = Runtime.getRuntime().exec("java -version");
Path path = Path.of("out.txt");
try (InputStream inputStream = proc.getErrorStream();
OutputStream outputStream = Files.newOutputStream(path)) {
inputStream.transferTo(outputStream);
}
, Reader
Writer
: Reader.transferTo()
, Java 10.
5. Collectors.teeing()
: Java 12
Stream
. , Stream
Employee
, :
Java 8? , : Stream.count()
, Stream.filter()
Stream.count()
. , Stream
.
– Stream.forEach()
:
Stream<Employee> employees = ...
int[] countWithPhoneAndTotal = {0, 0};
employees
.forEach(emp -> {
if (emp.getPhoneNumber() != null) {
countWithPhoneAndTotal[0]++;
}
countWithPhoneAndTotal[1]++;
});
System.out.println("Employees with phone number: "
+ countWithPhoneAndTotal[0]);
System.out.println("Total employees: "
+ countWithPhoneAndTotal[1]);
, , , . Stream.peek()
.
Stream.reduce()
:
class CountWithPhoneAndTotal {
final int withPhone;
final int total;
CountWithPhoneAndTotal(int withPhone, int total) {
this.withPhone = withPhone;
this.total = total;
}
}
CountWithPhoneAndTotal countWithPhoneAndTotal = employees
.reduce(
new CountWithPhoneAndTotal(0, 0),
(count, employee) -> new CountWithPhoneAndTotal(
employee.getPhoneNumber() != null
? count.withPhone + 1
: count.withPhone,
count.total + 1),
(count1, count2) -> new CountWithPhoneAndTotal(
count1.withPhone + count2.withPhone,
count1.total + count2.total));
System.out.println("Employees with phone number: "
+ countWithPhoneAndTotal.withPhone);
System.out.println("Total employees: "
+ countWithPhoneAndTotal.total);
, , . -, , -, , CountWithPhoneAndTotal
. - , CountWithPhoneAndTotal
inline
, .
. - , Java 8 , . , Java 12 Collectors.teeing()
:
Entry<Long, Long> countWithPhoneAndTotal = employees
.collect(teeing(
filtering(employee -> employee.getPhoneNumber() != null, counting()),
counting(),
Map::entry
));
.
Collectors.teeing()
: , - . : toBoth
, collectingToBoth
, collectingToBothAndThen
, pairing
, bifurcate
, distributing
, unzipping
, forking
,… teeing
tee, T, . : .
6. Runtime.version()
: Java 9
Java . , ? , . , java.version
. java.specification.version
… , :
for (String key : Arrays.asList(
"java.version",
"java.runtime.version",
"java.specification.version",
"java.vm.version",
"java.vm.specification.version")) {
System.out.println(key + " = " + System.getProperty(key));
}
Java 8, :
java.version = 1.8.0_192
java.runtime.version = 1.8.0_192-b12
java.specification.version = 1.8
java.vm.version = 25.192-b12
java.vm.specification.version = 1.8
8? , java.specification.version
, 1.
, … , Java 9 :
java.version = 9.0.1
java.runtime.version = 9.0.1+11
java.specification.version = 9
java.vm.version = 9.0.1+11
java.vm.specification.version = 9
, Java 9 API Java 10. API «» , Runtime.version()
. Runtime.Version
, :
Runtime.Version version = Runtime.version();
System.out.println("Feature = " + version.feature());
System.out.println("Interim = " + version.interim());
System.out.println("Update = " + version.update());
System.out.println("Patch = " + version.patch());
, , JDK 11.0.5:
Feature = 11
Interim = 0
Update = 5
Patch = 0
7. Optional.isEmpty()
: Java 11
, , :
if (!stream.findAny().isPresent()) {
System.out.println("Stream is empty");
}
Optional.isEmpty()
, :
if (stream.findAny().isEmpty()) {
System.out.println("Stream is empty");
}
:
Stream<Optional<Integer>> stream = Stream.of(
Optional.of(1),
Optional.empty(),
Optional.of(2));
long emptyCount = stream
.filter(Optional::isEmpty)
.count();
8. HTTP-
: Java 11
API HTTP HttpURLConnection
, Java . , : , HTTP/2 -, , . HTTP Client, Java 9 , Java 11.
java.net.http
, HttpClient
. , HTTP- :
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest
.newBuilder(new URI("https://minijug.ru"))
.build();
HttpResponse<Stream<String>> response = client.send(request,
HttpResponse.BodyHandlers.ofLines());
System.out.println("Status code = " + response.statusCode());
System.out.println("Body = ");
response.body().limit(4).forEach(System.out::println);
:
Status code = 200
Body =
<!doctype html>
<html>
<head>
<title>miniJUG</title>
java.net.http
, , .
9. Lookup.defineClass()
: Java 9
? , , Java 8 . Unsafe.defineClass()
Unsafe.defineAnonymousClass()
, API, .
: , , MethodHandles.Lookup.defineClass()
, Java 9. :
import java.lang.invoke.MethodHandles;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws Exception {
byte[] bytes = Files.readAllBytes(Path.of("Temp.class"));
Class<?> clazz = MethodHandles.lookup().defineClass(bytes);
Object obj = clazz.getDeclaredConstructor().newInstance();
System.out.println(obj);
}
}
class Temp {
@Override
public String toString() {
return "Hello from Temp!";
}
}
Temp
, Main
> javac Temp.java
> javac Main.java
> java Main
Hello from Temp!
, , Temp
Main
( , ). Temp
, - , Temp
, .
, , . defineClass()
, , . , . ToolProvider.getSystemJavaCompiler()
, java.compiler
( ).
10. ByteArrayOutputStream.writeBytes()
: Java 11
ByteArrayOutputStream.writeBytes()
– ByteArrayOutputStream.write()
: write()
throws IOException
, writeBytes()
– (IOException
write()
, OutputStream
). , Java 11, ByteArrayOutputStream
:
private static byte[] concat(Stream<byte[]> stream) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
stream.forEach(out::writeBytes);
return out.toByteArray();
}
: IndexOutOfBoundsException(int)
: Java 9
Java 9: IndexOutOfBoundsException
, , :
private static void doAtIndex(int index) {
if (index < 0) {
throw new IndexOutOfBoundsException(index);
}
}
public static void main(String[] args) {
doAtIndex(-1);
}
, 10 (+1) API, Java. ? , .