APIs for which it’s finally worth upgrading from Java 8. Part 2

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 -1if 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 Streaminherit 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.timeunder 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, :


  • Stream.
  • , .

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) //  opt -> !opt.isPresent()
    .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 = ");
//  4 
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. :


// Main.java
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);
    }
}

// Temp.java
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::write); ( )
    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) {
    // java.lang.IndexOutOfBoundsException: Index out of range: -1
    doAtIndex(-1);
}


, 10 (+1) API, Java. ? , .

Source: https://habr.com/ru/post/undefined/


All Articles