Вопросы для собеседования по Java (серия) — потоки
Все еще использую
for
петли? Возможно, пришло время для чего-то нового!
Говоря о Функциональные интерфейсы и Лямбда-выраженияэто правильно, что мы продолжаем нашу серию, говоря о Потоки.
Еще одна важная новая функция, появившаяся в Java 8, — это Stream
функциональность.
Прилагаемый пакет java.util.stream содержит классы, используемые для обработки последовательностей элементов.
Как вы, наверное, заметили из других постов, я не из тех, кто говорит только о теории.
Давайте посмотрим, как они играют, и поймем, как они работают. 🚀
Выполнение
💈 Лучшая аналогия для потоков — это pipe
, так это на самом деле упоминается в некоторых местах. В этой трубе у вас есть elements
приходят по одному.
🔵 Инициализация потоков
Существует несколько способов создания и инициализации потоков.
🔹 Пустой поток
Stream<Integer> emptyStream = Stream.empty();
Вы можете создать пустой поток, но на самом деле это не имеет смысла, за исключением того, что вы хотите создать Stream
каким-то другим образом, и он терпит неудачу, или условие ложно.
Например, вы можете ознакомиться с ofNullable
метод на Stream
сорт. Вторая часть не имеет большого значения, здесь вы можете увидеть, как пустой Stream
может быть использован.
public static<T> Stream<T> ofNullable(T t) {
return t == null ? Stream.empty()
: StreamSupport.stream(new Streams.StreamBuilderImpl<>
}
Stream.java
🔹 Поток.строитель()
Stream<Integer> streamUsingBuilder = Stream.<Integer>builder()
.add(1234)
.build();
Подход построителя может быть полезен, когда вы хотите добавить разные значения в поток на разных этапах приложения.
🔹 Поток()
Stream<Integer> stringStream = Stream.of(1, 2, 3, 4, 5);
Вы также можете инициализировать поток inline, используя static of
метод.
🔹 Массивы.stream()
Вы можете создать поток из массива, используя java.util.Arrays
сорт.
Integer[] intArray = new Integer[] {1,2,3,4,5};
Stream<Integer> intStream = Arrays.stream(intArray);
🔹 Коллекции.поток()
Collection
интерфейс получил новый метод взаимодействия с недавно добавленным Stream
сорт.
Благодаря этому любой объект, реализующий этот интерфейс, может быть преобразован в поток с помощью stream()
метод.
List<Integer> intList = new ArrayList<>();
Stream<Integer> intStreamFromList = intList.stream();
Set<Integer> intSet = new HashSet<>();
Stream<Integer> intStreamFromSet = intSet.stream();
После создания экземпляр не будет изменять свой источник, поэтому позволяет создавать несколько потоков из одного источника.
Мы видели, как мы можем инициализировать поток, давайте теперь поиграем с элементами.
Посмотрите больше подобных сообщений на new-spike.net
Пока они в трубе, вы можете:
🔸 изменить свое состояние
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Stream<String> stringStream = integerStream.map(val -> "Element: " + val); // Element: 1, Element: 2, Element: 3, Element: 4, Element: 5
Stream<Stream<Integer>> streamOfStreams = Stream.of(Stream.of(1), Stream.of(2,3), Stream.of(4,5,6));
Stream<String> integerStreams = streamsOfStreams.flatMap(val -> "Element: " + val); // Element: 1, Element: 2, Element: 3, Element: 4, Element: 5, Element: 6
🔸 отфильтровать некоторые из них
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
integerStream.filter(val -> val%2 == 0); // 2, 4
🔸 пропустить некоторые элементы
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
integerStream.skip(4) // 5
🔸 сортировать элементы
Stream<Integer> integerStream = Stream.of(3, 2, 1, 4, 5);
integerStream.sorted(); // 1, 2, 3, 4, 5
🔸 применять побочные эффекты
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
integerStream.peek(val -> System.out.println("Element: " + val)); // Element: 1, Element: 2, Element: 3, Element: 4, Element: 5
🔵 Терминальные операции
В конце трубы вы можете:
🔸 собрать элементы в другой набор данных
Stream<Integer> integerStream = Stream.of(1, 2, 1, 2, 1);
integerStream.collect(Collectors.toSet()); // 1, 2
🔸 вернуть один результат
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Integer sum = integerStream.reduce(0, (a, b) -> a+b); // 15
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Optional<Integer> result = integerStream.findFirst(); // Optional.of(1)
🔸 вернуть недействительным
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
integerStream.forEach(val -> System.out.println("Element: " + val)); // Element: 1, Element: 2, Element: 3, Element: 4, Element: 5
❗️ В потоке промежуточные операции «ленивы».
Вы можете применить к потоку столько, сколько хотите, но пока вы не примените терминальная операция промежуточные вызываться не будут.
Причина этого довольно проста, вам не нужно выделять и потреблять ресурсы, пока вам действительно не понадобится результат.
Посмотрите больше подобных сообщений на new-spike.net
🔵 Закрытие стримов
Streams
реализовать AutoCloseable
интерфейс, это означает, что они реализуют close()
метод.
❗️ Вы должны быть осторожны при закрытии потока, потому что после закрытия он выдаст IllegalStateException
если вы попытаетесь оперировать его снова.
Обычно вам не нужно закрывать потоки, так как их источники collections
или arrays
которые не требуют специального управления ресурсами.
❗️ Единственное исключение может быть, когда вы оперируете IO
ресурсы, такие как поток строк File
. Этот вариант использования потребует закрытия потока. ❗️
✅ Чтобы сделать это самым чистым способом, вы должны открыть поток в try-with-resources
блок, который будет автоматически обрабатывать закрытие потока после завершения всех операций.
Не пропустите больше таких сообщений! Подпишитесь на нашу бесплатную рассылку новостей!
В настоящее время я работаю над Java-интервью электронная книга, предназначенная для того, чтобы успешно пройти любое техническое собеседование по Java, которое вы можете пройти.
Следите за обновлениями! 🚀
Посмотрите больше подобных сообщений на new-spike.net