Interface Stream
A sequence of elements supporting sequential and parallel aggregate operations. The following example illustrates an aggregate operation using Stream and IntStream :
int sum = widgets.stream() .filter(w -> w.getColor() == RED) .mapToInt(w -> w.getWeight()) .sum();
In this example, widgets is a Collection
In addition to Stream , which is a stream of object references, there are primitive specializations for IntStream , LongStream , and DoubleStream , all of which are referred to as «streams» and conform to the characteristics and restrictions described here.
To perform a computation, stream operations are composed into a stream pipeline. A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc), zero or more intermediate operations (which transform a stream into another stream, such as filter(Predicate) ), and a terminal operation (which produces a result or side-effect, such as count() or forEach(Consumer) ). Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.
A stream implementation is permitted significant latitude in optimizing the computation of the result. For example, a stream implementation is free to elide operations (or entire stages) from a stream pipeline — and therefore elide invocation of behavioral parameters — if it can prove that it would not affect the result of the computation. This means that side-effects of behavioral parameters may not always be executed and should not be relied upon, unless otherwise specified (such as by the terminal operations forEach and forEachOrdered ). (For a specific example of such an optimization, see the API note documented on the count() operation. For more detail, see the side-effects section of the stream package documentation.)
Collections and streams, while bearing some superficial similarities, have different goals. Collections are primarily concerned with the efficient management of, and access to, their elements. By contrast, streams do not provide a means to directly access or manipulate their elements, and are instead concerned with declaratively describing their source and the computational operations which will be performed in aggregate on that source. However, if the provided stream operations do not offer the desired functionality, the BaseStream.iterator() and BaseStream.spliterator() operations can be used to perform a controlled traversal.
A stream pipeline, like the «widgets» example above, can be viewed as a query on the stream source. Unless the source was explicitly designed for concurrent modification (such as a ConcurrentHashMap ), unpredictable or erroneous behavior may result from modifying the stream source while it is being queried.
- must be non-interfering (they do not modify the stream source); and
- in most cases must be stateless (their result should not depend on any state that might change during execution of the stream pipeline).
Such parameters are always instances of a functional interface such as Function , and are often lambda expressions or method references. Unless otherwise specified these parameters must be non-null.
A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, «forked» streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. However, since some stream operations may return their receiver rather than a new stream object, it may not be possible to detect reuse in all cases.
Streams have a BaseStream.close() method and implement AutoCloseable . Operating on a stream after it has been closed will throw IllegalStateException . Most stream instances do not actually need to be closed after use, as they are backed by collections, arrays, or generating functions, which require no special resource management. Generally, only streams whose source is an IO channel, such as those returned by Files.lines(Path) , will require closing. If a stream does require closing, it must be opened as a resource within a try-with-resources statement or similar control structure to ensure that it is closed promptly after its operations have completed.
Stream pipelines may execute either sequentially or in parallel. This execution mode is a property of the stream. Streams are created with an initial choice of sequential or parallel execution. (For example, Collection.stream() creates a sequential stream, and Collection.parallelStream() creates a parallel one.) This choice of execution mode may be modified by the BaseStream.sequential() or BaseStream.parallel() methods, and may be queried with the BaseStream.isParallel() method.
- Java 8 Stream find
- 2. Stream findAny
- 3. Stream findFirst
- Как найти элемент в списке с помощью Java
- Дальнейшее чтение:
- Проверка Сортировки списка в Java
- Инициализация списка Java в одной строке
- 2. Настройка
- 3. Использование Java API
- 3.1. содержит()
- 3.2. Индекс()
- 3.3. Основные циклы
- 3.4. Цикл С итератором
- 3.5. Java 8 Stream API
- 4. Сторонние Библиотеки
- 4.1. Google Guava
- 4.2. Apache Commons
- 5. Заключение
- Читайте ещё по теме:
Java 8 Stream find
Stream API — новый способ взаимодействия с данными, представляя их в виде конечного потока данных.
Для поиска данных в Stream-е, необходимо использовать комбинации методов filter() и findAny() или findFirst()
2. Stream findAny
Метод findAny() возвращает первый попавшийся элемент из Stream-a, в виде обертки Optional.
Теперь найдем любую строку, в которой есть слово «Java»
Для обычных Stream-ов (последовательных) при нескольких запусках результат будет один и тот же. Для параллельных же — всегда разный
3. Stream findFirst
Метод findFirst() возвращает первый элемент по порядку из Stream-a, в виде обертки Optional.
Теперь найдем первое число, больше 10
В данном случае для обычных Stream-ов (последовательных) и для параллельных при нескольких запусках результат будет один и тот же, т.к. возвращается именно первый элемент по порядку в Stream-e.
Надеемся, что наша статья была Вам полезна. Также есть возможность записаться на наши курсы по Java в Киеве. Детальную информацию Вы можете найти у нас на сайте.
Как найти элемент в списке с помощью Java
Поиск элемента в списке-очень распространенная задача, с которой мы сталкиваемся как разработчики.
В этом кратком руководстве мы рассмотрим различные способы, которыми мы можем сделать это с помощью Java.
Дальнейшее чтение:
Проверка Сортировки списка в Java
Инициализация списка Java в одной строке
2. Настройка
Сначала давайте начнем с определения Customer POJO:
Listcustomers = new ArrayList<>(); customers.add(new Customer(1, "Jack")); customers.add(new Customer(2, "James")); customers.add(new Customer(3, "Kelly"));
Обратите внимание, что мы переопределили hashCode и equals в нашем классе Customer .
Исходя из нашей текущей реализации equals , два Customer объекта с одинаковым id будут считаться равными.
Мы будем использовать этот список клиентов по пути.
3. Использование Java API
Сама Java предоставляет несколько способов поиска элемента в списке:
3.1. содержит()
List предоставляет метод с именем содержит :
boolean contains(Object element)
Как следует из названия, этот метод возвращает true , если список содержит указанный элемент, и возвращает false в противном случае.
Поэтому, когда нам нужно проверить, существует ли конкретный элемент в нашем списке, мы можем:
Customer james = new Customer(2, "James"); if (customers.contains(james)) < // . >
3.2. Индекс()
indexOf – еще один полезный метод поиска элементов:
int indexOf(Object element)
Этот метод возвращает индекс первого вхождения указанного элемента в данный список или -1, если список не содержит элемента .
Таким образом, логически, если этот метод возвращает что-либо, кроме -1, мы знаем, что список содержит элемент:
if(customers.indexOf(james) != -1) < // . >
Главное преимущество использования этого метода заключается в том, что он может сообщить нам положение указанного элемента в данном списке.
3.3. Основные циклы
А что, если мы хотим выполнить поиск элемента на основе полей? Например, скажем, мы объявляем лотерею, и нам нужно объявить Клиента с определенным именем победителем.
Для таких полевых поисков мы можем обратиться к итерации.
Традиционный способ итерации по списку-использовать одну из циклических конструкций Java. На каждой итерации мы сравниваем текущий элемент в списке с элементом, который мы ищем, чтобы увидеть, соответствует ли он:
public Customer findUsingEnhancedForLoop( String name, Listcustomers) < for (Customer customer : customers) < if (customer.getName().equals(name)) < return customer; >> return null; >
Здесь имя относится к имени, которое мы ищем в данном списке клиентов . Этот метод возвращает первый Customer объект в списке с соответствующим именем или null , если такого Customer не существует.
3.4. Цикл С итератором
Итератор – это еще один способ обхода списка элементов.
Мы можем просто взять наш предыдущий пример и немного подправить его:
public Customer findUsingIterator( String name, Listcustomers) < Iterator iterator = customers.iterator(); while (iterator.hasNext()) < Customer customer = iterator.next(); if (customer.getName().equals(name)) < return customer; >> return null; >
Следовательно, поведение остается таким же, как и раньше.
3.5. Java 8 Stream API
Начиная с Java 8, мы также можем использовать Stream API для поиска элемента в списке .
Чтобы найти элемент, соответствующий определенным критериям в данном списке, мы:
- вызовите stream() в списке
- вызовите метод filter() с соответствующим предикатом
- вызовите конструкцию find Any () , которая возвращает первый элемент, соответствующий предикатуfilter, завернутому вOptional , если такой элемент существует
Customer james = customers.stream() .filter(customer -> "James".equals(customer.getName())) .findAny() .orElse(null);
Для удобства мы по умолчанию используем значение null в случае, если Необязательный пуст, но это не всегда может быть лучшим выбором для каждого сценария.
4. Сторонние Библиотеки
Теперь, хотя Stream API более чем достаточен, что нам делать, если мы застряли на более ранней версии Java?
К счастью, есть много сторонних библиотек, таких как Google Guava и Apache Commons, которые мы можем использовать.
4.1. Google Guava
Google Guava предоставляет функциональность, похожую на то, что мы можем сделать с потоками:
Customer james = Iterables.tryFind(customers, new Predicate() < public boolean apply(Customer customer) < return "James".equals(customer.getName()); >>).orNull();
Как и в случае с Stream API, мы можем дополнительно выбрать возврат значения по умолчанию вместо null :
Customer james = Iterables.tryFind(customers, new Predicate() < public boolean apply(Customer customer) < return "James".equals(customer.getName()); >>).or(customers.get(0));
Приведенный выше код выберет первый элемент в списке, если совпадение не будет найдено.
Кроме того, не забывайте, что Гуава бросает Исключение NullPointerException если либо список, либо предикат нулевой .
4.2. Apache Commons
Мы можем найти элемент почти точно таким же образом, используя Apache Commons:
Customer james = IterableUtils.find(customers, new Predicate() < public boolean evaluate(Customer customer) < return "James".equals(customer.getName()); >>);
Однако есть несколько важных отличий:
- Apache Commons просто возвращает null , если мы передаем список null .
- Ононе обеспечивает функциональность значений по умолчанию, как у Guavaпопробуй Найти.
5. Заключение
В этой статье мы изучили различные способы поиска элемента в списке , начиная с быстрых проверок существования и заканчивая полевыми поисками.
Мы также рассмотрели сторонние библиотеки Google Guava и Apache Commons как альтернативы Java 8 Streams API.
Спасибо, что заглянули, и не забудьте проверить все источники для этих примеров на GitHub.