Что выведет код?
#Tasks
import java.util.concurrent.CompletableFuture;
public class Task300626 {
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = new CompletableFuture<>();
CompletableFuture<String> result = future
.thenApply(s -> s + "!")
.exceptionally(ex -> "fallback");
future.completeExceptionally(new RuntimeException("Oops"));
System.out.println(result.get());
}
}
#Tasks
👍2
👍2
Какие методы появились в 🤓
Ответ:
Помимо repeat(), добавились:
isBlank() — возвращает true, если строка пуста или содержит только пробелы.
lines() — возвращает Stream<String> строк, разбитых по \n, \r, или \r\n.
strip() — удаляет пробелы в начале и конце (понимает Unicode, в отличие от trim()).
stripLeading() / stripTrailing() — соответственно. formatted(Object... args) — упрощает форматирование: "Hello %s".formatted("World").
Эти методы делают работу со строками более выразительной и безопасной.
#собеседование
String в Java 11? Ответ:
isBlank() — возвращает true, если строка пуста или содержит только пробелы.
lines() — возвращает Stream<String> строк, разбитых по \n, \r, или \r\n.
strip() — удаляет пробелы в начале и конце (понимает Unicode, в отличие от trim()).
stripLeading() / stripTrailing() — соответственно. formatted(Object... args) — упрощает форматирование: "Hello %s".formatted("World").
Эти методы делают работу со строками более выразительной и безопасной.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
История технологии сегодня — 01 июля
ℹ️ Кто родился в этот день
Михаи́л Миха́йлович Шульц (1 июля 1919 года, Петроград — 9 октября 2006 года, Санкт-Петербург) — учёный-химик, физикохимик, художник. Действительный член АН СССР (1979, с 1991 — РАН), Герой Социалистического Труда (1991), лауреат двух Государственных премий СССР. Шульц написал ряд работ по термодинамической теории, термодинамике гетерогенных систем, теории стёкол, химии и электрохимии стекла, мембранной электрохимии, теории ионного обмена и фазовых равновесий многокомпонентных систем, теории стеклянного электрода. С именем учёного связано становление pH-метрии и ионометрии, организация производства измерительной аппаратуры и материалов, широко используемых в медицине, химической и ядерной промышленности, в авиа- и ракетно-космической технике, в сельском хозяйстве и многих других областях.
🌐 Знаковые события
1896 — На Всероссийской промышленной выставке в Нижнем Новгороде представлен первый русский автомобиль (создатели — Евгений Яковлев и Пётр Фрезе).
#Biography #Birth_Date #Events #01июля
Михаи́л Миха́йлович Шульц (1 июля 1919 года, Петроград — 9 октября 2006 года, Санкт-Петербург) — учёный-химик, физикохимик, художник. Действительный член АН СССР (1979, с 1991 — РАН), Герой Социалистического Труда (1991), лауреат двух Государственных премий СССР. Шульц написал ряд работ по термодинамической теории, термодинамике гетерогенных систем, теории стёкол, химии и электрохимии стекла, мембранной электрохимии, теории ионного обмена и фазовых равновесий многокомпонентных систем, теории стеклянного электрода. С именем учёного связано становление pH-метрии и ионометрии, организация производства измерительной аппаратуры и материалов, широко используемых в медицине, химической и ядерной промышленности, в авиа- и ракетно-космической технике, в сельском хозяйстве и многих других областях.
1896 — На Всероссийской промышленной выставке в Нижнем Новгороде представлен первый русский автомобиль (создатели — Евгений Яковлев и Пётр Фрезе).
#Biography #Birth_Date #Events #01июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io)
SequenceInputStream – объединение потоков. Последовательное чтение и управление памятью
Ключевое архитектурное решение — ленивое переключение между потоками.
Конструкторы и внутреннее устройство
Конструктор с двумя потоками создает временный
Создание
Механика чтения и путь данных
Посимвольное чтение
Путь данных для
Критически важно:
Блочное чтение
Блочное чтение более эффективно: данные копируются напрямую из underlying потока в предоставленный массив без промежуточных буферов
#Java #для_новичков #beginner #IO #NIO #SequenceInputStream
Глава 1. Классический Java I/O (java.io)
SequenceInputStream – объединение потоков. Последовательное чтение и управление памятью
SequenceInputStream — декоратор над одним или несколькими InputStream, который представляет их как единый непрерывный поток. Данные читаются последовательно: сначала из первого потока до его исчерпания, затем из второго, и так далее. С точки зрения вызывающего кода это обычный InputStream — методы read(), available(), close() работают прозрачно, скрывая факт наличия нескольких underlying источников.Ключевое архитектурное решение — ленивое переключение между потоками.
SequenceInputStream не читает данные заранее и не буферизует их. Он делегирует вызовы текущему активному потоку, и только при достижении конца текущего потока (возврат -1) переключается на следующий. Это минимизирует потребление памяти: данные не дублируются, а передаются напрямую из underlying потоков в вызывающий код.Конструкторы и внутреннее устройство
// Упрощенная структура из OpenJDK
public class SequenceInputStream extends InputStream {
// Текущий активный поток
private InputStream in;
// Перечисление оставшихся потоков
private Enumeration<InputStream> e;
// Конструктор для двух потоков
public SequenceInputStream(InputStream s1, InputStream s2) {
Vector<InputStream> v = new Vector<>(2);
v.addElement(s1);
v.addElement(s2);
e = v.elements();
nextStream(); // Установка первого потока
}
// Конструктор для произвольного количества потоков
public SequenceInputStream(Enumeration<InputStream> e) {
this.e = e;
nextStream(); // Установка первого потока
}
// Переключение на следующий поток
private void nextStream() {
if (in != null) {
in.close(); // Закрытие исчерпанного потока
}
in = e.hasMoreElements() ? e.nextElement() : null;
}
}
Конструктор с двумя потоками создает временный
Vector — устаревшая synchronized коллекция. Это исторический артефакт: SequenceInputStream существует с Java 1.0, и Vector был стандартом того времени. Создание
Vector в heap — незначительная аллокация, но в современном коде предпочтительнее использовать конструктор с Enumeration, построенным из Iterator или Collections.enumeration().Механика чтения и путь данных
Посимвольное чтение
public int read() throws IOException {
if (in == null) {
return -1; // Все потоки исчерпаны
}
int c = in.read(); // Делегирование текущему потоку
if (c == -1) {
nextStream(); // Переключение на следующий
return read(); // Рекурсивный вызов для нового потока
}
return c;
}Путь данных для
read():[Java: sis.read()]
-> [SequenceInputStream: in != null?]
-> [in.read()] // Делегирование текущему потоку
-> [Например, FileInputStream.read()]
-> [Системный вызов read()]
-> [Page Cache -> нативный буфер -> byte в heap]
-> [c == -1?] // Конец текущего потока?
-> [Нет: возврат c]
-> [Да: nextStream()]
-> [in.close()] // Закрытие исчерпанного потока
-> [in = e.nextElement()] // Следующий поток
-> [Рекурсивный read()] // Чтение из нового потока
Критически важно:
nextStream() автоматически закрывает исчерпанный поток. Это предотвращает утечку файловых дескрипторов. Однако если underlying потоки не поддерживают повторное открытие (как FileInputStream), они становятся недоступны после закрытия.Блочное чтение
public int read(byte[] b, int off, int len) throws IOException {
if (in == null) {
return -1;
}
if (b == null) {
throw new NullPointerException();
}
int n = in.read(b, off, len); // Попытка чтения из текущего потока
if (n > 0) {
return n; // Данные прочитаны
}
if (n == -1) {
nextStream(); // Конец потока — переключение
return read(b, off, len); // Рекурсивный вызов
}
// n == 0: поток вернул 0 байт, но не EOF
return 0;
}Блочное чтение более эффективно: данные копируются напрямую из underlying потока в предоставленный массив без промежуточных буферов
SequenceInputStream. Это минимизирует копирование в памяти.#Java #для_новичков #beginner #IO #NIO #SequenceInputStream
👍3
Роль garbage collector
Жизненный цикл объектов
Анализ памяти:
При закрытии
Проблема: утечка при исключении
Если
Практический пример: склеивание текстовых файлов
Путь данных при склеивании текстовых файлов
Ограничения и альтернативы
Невозможность произвольного доступа
Отсутствие буферизации
Современная альтернатива: Stream API Java 8
#Java #для_новичков #beginner #IO #NIO #SequenceInputStream
Жизненный цикл объектов
public void concatenateFiles(String outputPath, String... inputPaths)
throws IOException {
// Создание Enumeration из списка путей
Vector<InputStream> streams = new Vector<>();
for (String path : inputPaths) {
streams.add(new FileInputStream(path)); // Каждый поток — объект в heap
}
// SequenceInputStream создается в heap
// Внутренний Vector — объект в heap
try (SequenceInputStream sis = new SequenceInputStream(streams.elements());
FileOutputStream fos = new FileOutputStream(outputPath)) {
byte[] buffer = new byte[8192]; // Буфер в heap
int bytesRead;
// Цикл без аллокаций — GC не вовлечен
while ((bytesRead = sis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
} // sis.close() закрывает текущий поток и все оставшиеся в Enumeration
// Vector, FileInputStream'ы, buffer — недостижимы, GC собирает
}
Анализ памяти:
Vector<InputStream> — коллекция в heap, содержит ссылки на все потокиFileInputStream для каждого файла — объекты в heap с файловыми дескрипторамиSequenceInputStream — объект в heap с ссылкой на Vector и текущий потокbuffer[8192] — массив в heap, переиспользуется в циклеПри закрытии
SequenceInputStream через try-with-resources вызывается close(), который закрывает текущий поток и все оставшиеся потоки в Enumeration. Это гарантирует освобождение файловых дескрипторов.Проблема: утечка при исключении
// Антипаттерн: утечка при исключении в конструкторе
Vector<InputStream> streams = new Vector<>();
for (String path : paths) {
streams.add(new FileInputStream(path)); // Если здесь исключение — предыдущие потоки не закрыты
}
SequenceInputStream sis = new SequenceInputStream(streams.elements());
Если
new FileInputStream() выбрасывает FileNotFoundException на N-м файле, предыдущие N-1 потоков остаются открытыми. Решение — явное управление ресурсами:// Правильно: гарантированное закрытие при исключении
List<InputStream> streams = new ArrayList<>();
try {
for (String path : paths) {
streams.add(new FileInputStream(path));
}
Enumeration<InputStream> en = Collections.enumeration(streams);
try (SequenceInputStream sis = new SequenceInputStream(en)) {
// Использование
}
} catch (IOException e) {
// Закрытие всех созданных потоков при ошибке
for (InputStream is : streams) {
try { is.close(); } catch (IOException ignored) {}
}
throw e;
}
Практический пример: склеивание текстовых файлов
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class FileConcatenator {
// Объединение файлов с автоматическим закрытием
public void concatenate(String outputPath, String... inputPaths)
throws IOException {
// Создание списка потоков с гарантированным закрытием при ошибках
List<InputStream> streams = new ArrayList<>();
boolean success = false;
try {
for (String path : inputPaths) {
streams.add(new FileInputStream(path));
}
// SequenceInputStream объединяет все потоки
Enumeration<InputStream> en = Collections.enumeration(streams);
try (SequenceInputStream sis = new SequenceInputStream(en);
// Декодирование байтов в символы через UTF-8
InputStreamReader isr = new InputStreamReader(sis, StandardCharsets.UTF_8);
// Буферизация символьного ввода
BufferedReader reader = new BufferedReader(isr);
// Запись в выходной файл
FileOutputStream fos = new FileOutputStream(outputPath);
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter writer = new BufferedWriter(osw)) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
success = true;
}
} finally {
// Закрытие всех потоков, если try-with-resources не сработал
if (!success) {
for (InputStream is : streams) {
try { is.close(); } catch (IOException ignored) {}
}
}
}
}
// Альтернатива: объединение только двух файлов
public void concatenateTwo(String outputPath, String path1, String path2)
throws IOException {
try (SequenceInputStream sis = new SequenceInputStream(
new FileInputStream(path1),
new FileInputStream(path2));
FileOutputStream fos = new FileOutputStream(outputPath)) {
// Прямое блочное копирование без промежуточных преобразований
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = sis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
}
// Оба FileInputStream закрыты автоматически:
// - первый при исчерпании (внутри nextStream)
// - второй при закрытии SequenceInputStream
}
}
Путь данных при склеивании текстовых файлов
[Файл 1 на диске: байты UTF-8]
-> [FileInputStream 1: системный вызов read()]
-> [SequenceInputStream: делегирование FileInputStream 1]
-> [InputStreamReader: декодирование байт -> char]
-> [BufferedReader: накопление в cb[8192], поиск \n]
-> [readLine(): создание String]
-> [BufferedWriter.write(String)]
-> [OutputStreamWriter: кодирование char -> байты UTF-8]
-> [FileOutputStream: системный вызов write()]
-> [Page Cache -> диск]
[Конец файла 1: FileInputStream 1.read() возвращает -1]
-> [SequenceInputStream.nextStream()]
-> [FileInputStream 1.close()] // Автоматическое закрытие
-> [FileInputStream 2 становится активным]
[Файл 2 на диске: байты UTF-8]
-> [FileInputStream 2: системный вызов read()]
-> [SequenceInputStream: делегирование FileInputStream 2]
-> [Тот же путь через Reader/Writer]
Ограничения и альтернативы
Невозможность произвольного доступа
SequenceInputStream — строго последовательный. После переключения на следующий поток вернуться к предыдущему невозможно — он закрыт. Это отличает его от ConcatenationInputStream в некоторых библиотеках или от ручного управления массивом потоков.Отсутствие буферизации
SequenceInputStream не имеет собственного буфера. Если underlying потоки не буферизованы, каждый read() инициирует системный вызов. Рекомендуется оборачивать underlying потоки в BufferedInputStream:// Правильно: буферизация каждого потока
Vector<InputStream> streams = new Vector<>();
for (String path : paths) {
streams.add(new BufferedInputStream(new FileInputStream(path)));
}
SequenceInputStream sis = new SequenceInputStream(streams.elements());
Современная альтернатива: Stream API Java 8
// Объединение через Stream API — более гибко, но с другой семантикой
public void concatenateModern(String outputPath, String... inputPaths)
throws IOException {
try (OutputStream out = new FileOutputStream(outputPath)) {
for (String path : inputPaths) {
Files.copy(Path.of(path), out); // Копирование файла в общий поток
}
}
}
Files.copy() использует transferTo() — оптимизированный механизм копирования через FileChannel, потенциально с zero-copy на уровне ОС. Это более эффективно, чем SequenceInputStream с промежуточным буфером.#Java #для_новичков #beginner #IO #NIO #SequenceInputStream
👍3
Что выведет код?
#Tasks
import java.io.*;
public class Task010726 {
public static void main(String[] args) throws IOException {
ByteArrayInputStream bais1 = new ByteArrayInputStream(new byte[]{1, 2, 3});
ByteArrayInputStream bais2 = new ByteArrayInputStream(new byte[]{4, 5, 6});
SequenceInputStream sis = new SequenceInputStream(bais1, bais2);
byte[] buffer = new byte[5];
int len = sis.read(buffer, 0, 5);
System.out.println(len);
for (int i = 0; i < len; i++) {
System.out.print(buffer[i] + " ");
}
}
}
#Tasks
👍3
👍3
Водопад Корбу
🔥11
Что такое 🤓
Ответ:
В Java 11 добавлены удобные методы для чтения и записи строк из/в файл:
Files.readString(Path path) — читает весь файл в строку (используя UTF-8).
Files.writeString(Path path, CharSequence csq) — записывает строку в файл.
Поддерживают опции StandardOpenOption. Это избавляет от рутины с BufferedReader и FileWriter для простых сценариев.
Пример: String content = Files.readString(Path.of("file.txt"));. Подходят для небольших файлов (для больших использовать стримы).
#собеседование
Files.readString() и writeString()? Ответ:
Files.readString(Path path) — читает весь файл в строку (используя UTF-8).
Files.writeString(Path path, CharSequence csq) — записывает строку в файл.
Поддерживают опции StandardOpenOption. Это избавляет от рутины с BufferedReader и FileWriter для простых сценариев.
Пример: String content = Files.readString(Path.of("file.txt"));. Подходят для небольших файлов (для больших использовать стримы).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6