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 stream сортировка по полю
Коллекции, на основе которых нередко создаются потоки, уже имеют специальные методы для сортировки содержимого. Однако класс Stream также включает возможность сортировки. Такую сортировку мы можем задействовать, когда у нас идет набор промежуточных операций с потоком, которые создают новые наборы данных, и нам надо эти наборы отсортировать.
Для простой сортировки по возрастанию применяется метод sorted() :
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Program < public static void main(String[] args) < Listphones = new ArrayList(); Collections.addAll(phones, "iPhone X", "Nokia 9", "Huawei Nexus 6P", "Samsung Galaxy S8", "LG G6", "Xiaomi MI6", "ASUS Zenfone 3", "Sony Xperia Z5", "Meizu Pro 6", "Pixel 2"); phones.stream() .filter(p->p.length()<12) .sorted() // сортировка по возрастанию .forEach(s->System.out.println(s)); > >
Консольный вывод после сортировки объектов:
LG G6 Meizu Pro 6 Nokia 9 Pixel 2 Xiaomi MI6 iPhone X
Однако данный метод не всегда подходит. Уже по консольному выводу мы видим, что метод сортирует объекты по возрастанию, но при этом заглавные и строчные буквы рассматриваются отдельно.
Кроме того, данный метод подходит только для сортировки тех объектов, которые реализуют интерфейс Comparable .
Если же у нас классы объектов не реализуют этот интерфейс или мы хотим создать какую-то свою логику сортировки, то мы можем использовать другую версию метода sorted() , которая в качестве параметра принимает компаратор.
Например, пусть у нас есть следующий класс Phone:
class Phone < private String name; private String company; private int price; public Phone(String name, String comp, int price)< this.name=name; this.company=comp; this.price = price; >public String getName() < return name; >public int getPrice() < return price; >public String getCompany() < return company; >>
Отсортируем поток обектов Phone:
import java.util.Comparator; import java.util.stream.Stream; public class Program < public static void main(String[] args) < StreamphoneStream = Stream.of(new Phone("iPhone X", "Apple", 600), new Phone("Pixel 2", "Google", 500), new Phone("iPhone 8", "Apple",450), new Phone("Nokia 9", "HMD Global",150), new Phone("Galaxy S9", "Samsung", 300)); phoneStream.sorted(new PhoneComparator()) .forEach(p->System.out.printf("%s (%s) - %d \n", p.getName(), p.getCompany(), p.getPrice())); > > class PhoneComparator implements Comparator < public int compare(Phone a, Phone b)< return a.getName().toUpperCase().compareTo(b.getName().toUpperCase()); >>
Здесь определен класс компаратора PhoneComparator, который сортирует объекты по полю name. В итоге мы получим следующий вывод:
Galaxy S9 (Samsung) - 300 iPhone 8 (Apple) - 450 iPhone X (Apple) - 600 Nokia 9 (HMD Global) - 150 Pixel 2 (Google) - 500
Java Stream sorted example
In this post, we will see how to sort a list with Stream.sorted() method.
Java 8 has introduced Stream.sort() method to sort list of elements conveniently. It helps us to write short and concise functional style code rather than boilerplate code.
- sorted() : Returns a stream having elements sorted by natural order
- sorted(Comparator comparator) : Returns a stream having elements sorted by provided comparator
💡 Did you know?
If you sort list of Integers using Stream.sorted() method then Comparable interface, implemented by Integer class, will define natural ordering of list of Integers .
Let’s understand how can we use Stream.sorted() to sort list of elements.
Sort List of Integers
We can simply use sorted() method to sort list of integers.
Here, List of Integers is sorted by Comparable interface implemented by Integer class.
As you can see, Integers are compared on this basis of (x < y) ? -1 : ((x == y) ? 0 : 1) logic.
You can pass Comparator.reverseOrder() to sorted method to reverse sort list of Integers.
Comparator.reverseOrder() is static method and provides a comparator that imposes reverse of natural ordering.
Let’s see complete example to sort list of integers.
Sort List of Strings
We can simply use sorted() method to sort list of Strings.
Here, List of Strings is sorted by Comparable interface implemented by String class.
As you can see, Integers are compared on this basis of (x < y) ? -1 : ((x == y) ? 0 : 1) logic.
You can pass Comparator.reverseOrder() to sorted method to reverse sort list of Integers.
Comparator.reverseOrder() is static method and provides a comparator that imposes reverse of natural ordering.
Let’s see complete example to sort list of integers.
Sort List of custom objects
Sort list of Students by natural order
Create a class named Student.java
Let’s use Stream’s sorted() to sort the list of Students now.
Exception in thread “main” java.lang.ClassCastException: org.arpit.java2blog.Student cannot be cast to java.lang.Comparable
at java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.util.TimSort.sort(TimSort.java:220)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:353)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:483)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
at org.arpit.java2blog.SortListOfStudents.main(SortListOfStudents.java:14)
Did you know why we got exception here?
We got the ClassCastException exception because we did not implement Comparable interface in Student class.
Let’s implement Comparable interface in Student class.