Java
中的Stream
(流)被定义为支持聚合操作的源的一系列元素序列。这里的源指的是向Stream
提供数据的Collections
或Arrays.
Stream
保持数据在源中的顺序。这种聚合操作或批量操作允许我们更轻松而清晰的对stream
元素作出常见的操作。
在开始之前,了解Java 8 Streams
的设计方式是绝大多数stream
操作只返回streams
是很重要的。这帮助我们创建了stream
操作链。这被称作为pipe-lining
(管道链)。
lambda
)设计arrays
或list
)public class StreamBuilders
{
public static void main(String[] args)
{
Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9);
stream.forEach(p -> System.out.println(p));
}
}
public class StreamBuilders
{
public static void main(String[] args)
{
Stream<Integer> stream = Stream.of( new Integer[]{1,2,3,4,5,6,7,8,9} );
stream.forEach(p -> System.out.println(p));
}
}
public class StreamBuilders
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
stream.forEach(p -> System.out.println(p));
}
}
public class StreamBuilders
{
public static void main(String[] args)
{
Stream<Date> stream = Stream.generate(() -> { return new Date(); });
stream.forEach(p -> System.out.println(p));
}
}
public class StreamBuilders
{
public static void main(String[] args)
{
IntStream stream = "12345_abcdefg".chars();
stream.forEach(p -> System.out.println(p));
//OR
Stream<String> stream = Stream.of("A$B$C".split("\\$"));
stream.forEach(p -> System.out.println(p));
}
}
public class StreamBuilders {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
List<Integer> evenNumbersList = stream.filter(i -> i%2 == 0).collect(Collectors.toList());
System.out.print(evenNumbersList);
}
}
public class StreamBuilders {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i = 1; i< 10; i++){
list.add(i);
}
Stream<Integer> stream = list.stream();
Integer[] evenNumbersArr = stream.filter(i -> i%2 == 0).toArray(Integer[]::new);
System.out.print(evenNumbersArr);
}
}
还有许多其他的方式可以将stream
收集到set,map
或多个方法中,只要通过Collectors
类并且记住他们他们.
首先先建立一个字符串集合,我们将在这个列表上建立一个示例.
List<String> memberNames = new ArrayList<>();
memberNames.add("Amitabh");
memberNames.add("Shekhar");
memberNames.add("Aman");
memberNames.add("Rahul");
memberNames.add("Shahrukh");
memberNames.add("Salman");
memberNames.add("Yana");
memberNames.add("Lokesh");
这些核心方法分为以下两部分:
Intermediate operations
返回stream
本身,因此可以在一行中链式调用多个方法.
Filter
接收一个predicate
来过滤stream
(流)中所有元素,这是一个中间操作,它允许我们对结果调用另一个stream
操作.(比如forEach)
memberNames.stream().filter((s)>s.startsWith("A"))
.forEach(System.out::println);
输出为:
Amitabh
Aman
Intermediate operation
通过给定的函数可以将stream
中的每个元素转换为另一个对象.下面的示例将每个字符串转换为大写.也可以使用map
将对象转换为另一种类型.
memberNames.stream().filter((s)->s.startsWith("A"))
.map(String::toUpperCase)
.forEach(System.out::println);
输出:
AMITABH
AMAN
Sorted
是一个返回已排序stream
视图的中间操作,该排序规则,除非传递一个自定义比较器,否则元素自然排序.
memberNames.stream().sorted()
.map(String::toUpperCase)
.forEach(System.out::println);
输出结果:
AMAN
AMITABH
LOKESH
RAHUL
SALMAN
SHAHRUKH
SHEKHAR
YANA
Terminal operations
返回特定类型的结果,而非是stream
这个方法帮助遍历stream
中的所有元素,并且对其执行某些操作.这种操作通过lambda
表达式参数传递.
memberNames.forEach(System.out::println);
collect()
方法用于从stream
中接收元素并且存储到collection
中.
List<String> memNamesInUpper=memberNames.stream().sorted()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(memNamesInUpper);
输出结果:
[AMAN, AMITABH, LOKESH, RAHUL, SALMAN, SHAHRUKH, SHEKHAR, YANA]
各种matching
(匹配)操作被用来检查某个predicate
(断言)是否与stream
匹配.所有这些操作都是终端操作,并返回一个boolean
值.
boolean matchedResult = memberNames.stream().anyMatch((s) -> s.startsWith("A"));
System.out.println(matchedResult);
matchedResult = memberNames.stream().allMatch((s) -> s.startsWith("A"));
System.out.println(matchedResult);
matchedResult = memberNames.stream().noneMatch((s) -> s.startsWith("A"));
System.out.println(matchedResult);
输出结果:
true
false
false
Count
是一个返回stream
中元素数量的结果操作,返回值为long
型.
long total=memberNames.stream()
.filter((s)->s.startsWith("A"))
.count();
System.out.println(total);
输出结果:
2
该terminal operation
使用给定函数对stream
中元素执行缩减,这个结果是一个包含缩减后的值的Optional
.
Optional<String> reduced=memberNames.stream()
.reduce((s1,s2)->s1+"#"+s2);
reduced.ifPresent(System.out::println);
输出为:
Amitabh#Shekhar#Aman#Rahul#Shahrukh#Salman#Yana#Lokesh
尽管stream
操作是在满足一个predicate
的集合中的所有元素上执行的,但在迭代过程中每当遇到匹配元素时,通常都希望结束这个操作.在外部迭代中,你将使用if-else
语句块,而在内部迭代中,也可以使用特定方法达到这个目的.
当predicate
满足条件,则返回true
,它将不再处理更多元素.
boolean metched=memberNames.stream()
.anyMatch((s)->s.startWith("A"));
System.out.println(metched);
输出结果:
true
该方法返回stream
中的第一个元素并且不再处理任何其他的元素.
String firstMatchedName=memberNames.stream()
.filter((s)->s.startWith("L"))
.findFirst().get();
System.out.println(firstMatchedName);
输出结果:
Lokesh
通过再Java7
中加入Fork/Join
框架,我们可以更高效的再引用程序中实现并行操作.但实现这个框架本身是一项复杂的任务,如果出现错误,这就是复杂多线程出现Bug
的一个源头.随着Java
内部迭代的引入,使得并行操作有了更易操作的可能性.
为实现parallelism
,只需要创建一个parallel stream
(并行流),而不是sequential stream
.可以发现,这是很简单的,在上述的多个示例中,如果你要 在并行内核中使用多个线程执行特定任务,只需要调用parallelStream()
而不是stream()
List<Integer> list = new ArrayList<>();
for (int i = 1; i < 10; i++)
list.add(i);
// creating a parallel stream
Stream<Integer> stream = list.parallelStream();
Integer[] evenNumbersArr = stream.filter(i -> i % 2 == 0)
.toArray(Integer[]::new);
System.out.println(Arrays.toString(evenNumbersArr));
输出结果:
[2,4,6,8]
Intermediate Operations
Terminal Operations