JAVA8 Stream
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。
- 聚合操作:
对一个数据集合的数进行处理,如分类,取最值,去重等操作- Stream类似迭代器,进行遍历对数据进行操作,不同的是Stream可以并行化的执行操作(Fork/Join 框架),Stream 的另外一大特点是,数据源本身可以是无限的。
Stream三种操作
1,Intermediate(相当于添加遍历时的操作)
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
- 一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
2,Terminal(相当于根据操作进行遍历,遍历后流消失)
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
- 一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
3,short-circuiting(操作无限大的数据源时使用)
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
- 对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
- 对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
1,获取流,流转换
public class StreamTest {
public static void main(String[] args) {
// 1. Individual values
Stream<String> stream = Stream.of("a", "b", "c");
// 2. Arrays
String[] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();
// 4. IntStream、LongStream、DoubleStream
int[] arrInt = new int[]{1,4,34,5};
//IntStream.of(arrInt).forEach(System.out::print);
//返回1234567
IntStream.range(1, 8).forEach(System.out::print);
// 5.流转换为集合等其他数据结构(每个流只能使用一次)
String[] strArray1 = (String[]) stream.toArray(String[]::new);
stream = list.stream();
List<String> list1 = (List<String>) stream.collect(Collectors.toList());
stream = list.stream();
List<String> list2 = (List<String>) stream.collect(Collectors.toCollection(ArrayList::new));
stream = list.stream();
Set set1 = (Set) stream.collect(Collectors.toSet());
stream = list.stream();
Stack stack1 = (Stack) stream.collect(Collectors.toCollection(Stack::new));
}
}
2,遍历集合(Terminal)
forEach之后流不可以再被使用
public class StreamTest {
public static void main(String[] args) {
String[] arr = {"cde","bcd","abc","efg","fgh", "def"};
List<String> list = Arrays.asList(arr);
//获取流
Stream<String> stringStream = list.stream();
//遍历输出
stringStream.forEach(System.out::println);
}
}
3,map的使用(Intermediate)
它的作用就是把 input Stream 的每一个元素,映射成 output Stream 的另外一个元素
public class StreamTest {
public static void main(String[] args) {
//map的使用
String[] arr = {"cde","bcd","abc","efg","fgh", "def"};
List<String> list = Arrays.asList(arr);
//获取流
Stream<String> stringStream = list.stream();
//转换大小写,输出
stringStream.map(String::toUpperCase).forEach(System.out::println);
}
}
4,flatMap的使用(Intermediate)
一对多的使用,flatMap 把 input Stream 中的层级结构扁平化,就是将最底层元素抽出来放到一起,最终 output 的新 Stream 里面已经没有 List 了,都是直接的数字。
public class StreamTest {
public static void main(String[] args) {
//map的使用
String[] arr = {"cde","bcd","abc","efg","fgh", "def"};
String[] arr2 = {"xxx","yyy","zzz"};
List<String> list = Arrays.asList(arr);
List<String> list2 = Arrays.asList(arr2);
//获取流
Stream<List<String>> inputStream = Stream.of(list,list2);
inputStream.flatMap((childList) -> childList.stream()).forEach(System.out::println);
}
}
5,filter(Intermediate)
过滤数据
public class StreamTest {
public static void main(String[] args) {
//map的使用
String[] arr = {"cde","bdcd","abc","cfg","fgh", "def"};
String[] arr2 = {"aaa","bcdd","abcd"};
List<String> list = Arrays.asList(arr);
//获取流
Stream<String[]> inputStream = Stream.of(arr, arr2);
inputStream.flatMap(childList -> Arrays.stream(childList))
//取长度大于3的字符串
.filter(string -> string.length() > 3)
.forEach(System.out::println);
}
}
6,peek (Intermediate)
对每一个元素执行操作后返回新的流,forEach之后流就不可以使用了
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(new Integer[]{1,2,3,4,5});
list = list.stream().filter(num -> num>3)
.peek(num ->
System.out.println("获取到了"+num)
).peek(num ->
System.out.println("获取到了"+num)
)
.collect(Collectors.toList());
System.out.println(list);
}
}