简介
Stream
称之为流
流的构成
- 源(各种集合)
- 零个或多个中间操作(对集合中元素的修改和操作)
- 终止操作(输出、求和。。。)
创建流
public class StreamTest1 {
public static void main(String[] args) {
int[] a = new int[]{2,4,6,8,7,9,13,16,17};
Integer[] b = new Integer[]{2,4,6,8,7,9,13,16,17};
Stream stream = Stream.of(a);
Stream stream1 = Stream.of("asdf","Asdfsa","sadgggg");
Stream stream2 = Arrays.stream(b);//基本数据类型数组不行,得是对象数组,如,String 、Integer。。。。
List<Integer> list = Arrays.asList(b);
Stream stream3 = list.stream();
}
}
稍微特殊的流
IntStream
public class StreamTest2 {
public static void main(String[] args) {
IntStream.range(6,13).forEach( s -> System.out.print(s+" "));//左开右闭区间
}
}
继续体验流
将集合中的每个元素乘2并求和
public class StreamTest3 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
System.out.println(list.stream().map(i -> i * 2).reduce(0, (i, s) -> s = s + i));
}
}
- 代码释义
如果
reduce
第一个参数是6
,那么s
的初始值就是6
,最后结果就是36
了
再者
再继续体验
- 将流中的数据,变成数组,并打印。
- 可以使用Stream中的
toArray
方法
public class StreamTest4 {
public static void main(String[] args) {
Stream<String> stream = Stream.of("AABB","CCDD","EEFF","GGHH");
// System.out.println(stream.count());//求stream中元素个数
String[] stringArray = stream.toArray(length -> new String[length]);
//调用toArray时,length会自动求出来
Arrays.asList(stringArray).forEach(System.out::println);
//将数组转换成集合。并用forEach,再引用方法,实现forEach参数Consumer
}
}
Stream.of("AABB","CCDD","EEFF","GGHH");
不能认为丢进去的元素就已经是数组了,of(T...)的参数是可变长参数,只是表示丢进去多个参数而已,是不是数组得另说
- 或者使用方法引用
public class StreamTest4 {
public static void main(String[] args) {
Stream<String> stream = Stream.of("AABB","CCDD","EEFF","GGHH");
String[] stringArray = stream.toArray(String[]::new);//引用构造方法
Arrays.asList(stringArray).forEach(System.out::println);
}
}
使用stream.collect( . . .)
继续
将流中的数据变成List
- 先上一个耳熟能详的
Collectors.toList()
public class StreamTest5 {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(11,22,33,44,55,66);
List<Integer> list = stream.collect(Collectors.toList());
list.forEach(l -> System.out.print(l+" "));
}
}
- 再来一个看不懂的
public class StreamTest5 {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(11,22,33,44,55,66);
List<Integer> list2 = stream.collect( () -> new ArrayList<Integer>(),
(resList,item) -> resList.add(item),
(resList1,resList) -> resList1.addAll(resList));// stream.collect接收3个参数,看仔细了
list2.forEach(l -> System.out.print(l+" "));//打印
}
}
- 上面的代码可以使用方法引用
List<Integer> list2 = stream.collect(ArrayList::new, ArrayList::add,
ArrayList::addAll);
- 看看代码
再者
- 你可能会认为
Collectors.toList()
已经够了
- 说明:
Collectors.toList()
只返回ArrayList
,如果需要LinkedList
或其他,还得手写stream.collect
的三个参数(提供商,累加器,组合器)的实现
稍微使用一下神器Collectors
stream.collect(Collectors.toList())
,这个就不说了Collectors.toCollection(集合的实现类::new)
//获得你想要的集合
public class CollectsTest {
public static void main(String[] args) {
Stream<String> stream = Stream.of("AABB","CCDD","EEFF","GGHH");
//将stream转成ArrayList
List<String> stringList = stream.collect(Collectors.toCollection(ArrayList::new));
System.out.println(stringList.getClass());
}
}
- 同理
public class CollectsTest {
public static void main(String[] args) {
Stream<String> stream = Stream.of("AABB","CCDD","EEFF","GGHH");
//将stream转成TreeSet
Set<String> stringSet = stream.collect(Collectors.toCollection(TreeSet::new));
System.out.println(stringSet.getClass());
}
}
- 关于
Collectors.toCollection(集合的实现类::new)
的实现还是喜闻乐见的三人帮(提供商,累加器,组合器)
- 拼接,以指定的分隔符拼接不同元素形成String
public class CollectsTest {
public static void main(String[] args) {
Stream<String> stream = Stream.of("AABB","CCDD","EEFF","GGHH");
String str = stream.collect(Collectors.joining("00")); //以00为分隔符拼接成String
System.out.println(str);
// Collectors.joining返回值是String
}
}
- 将集合中的String元素变成大写
public class StreamTest6 {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("aabb","ccdd","eeff","gghh");
stringList.stream().map(String::toUpperCase).forEach(System.out::println);
}
}
操作List里面的List中的元素,并将多个List的元素放到一个List中
- 你可能会想当然
- 正确解法
public class FlatMap {
public static void main(String[] args) {
Stream<List<Integer>> listStream = Stream.of(Arrays.asList(2,4,7),Arrays.asList(8,8),Arrays.asList(13,19));
//扁平化映射
List<Integer> list = listStream.flatMap(ls -> ls.stream()).map(item ->item*item).collect(Collectors.toList());
list.forEach(System.out::println);
}
}
再来几个应用
和Optional
相关
- 体验一下无限流
generate()
public class StreamTest7 {
public static void main(String[] args) {
Stream<String> stream = Stream.generate(UUID.randomUUID()::toString);//一个新的无限顺序无序Stream
stream.forEach(System.out::println);//输出不会结束
}
}
- 使用
findFirst()
,返回Optional
并将第一个元素封装进去
public class StreamTest7 {
public static void main(String[] args) {
Stream<String> stream = Stream.generate(UUID.randomUUID()::toString);//一个新的无限顺序无序Stream
stream.findFirst().ifPresent(System.out::println);
//一定要先判断返回的是不是空的Optional,再进行其他操作,防止空指针异常
}
}
另外一种无限流
iterate(final T seed, final UnaryOperator<T> f)
public class StreamTest7 {
public static void main(String[] args) {
//种子0,就是i的初始值 return i=(i+1)%2
Stream.iterate(0 ,i -> (i+1)%2).forEach(System.out::println);//无限输出0和1
}
}
- 中断无限流
有瑕疵的操作
,即输出没有无限,但流没有中断
public class StreamTest7 {
public static void main(String[] args) {
//去除重复元素,//提取前面6个
Stream.iterate(0 ,i -> (i+1)%2).distinct().limit(6).forEach(System.out::println);
//只输出 0和1 ,但程序不会结束
}
}
- 正常结束它
public class StreamTest7 {
public static void main(String[] args) {
Stream.iterate(0 ,i -> (i+1)%2).limit(6).distinct().forEach(System.out::println);
}
}
先截取固定个数的元素后去除重复才正常。因为流是无限的,先去重的话工作是不会结束的,所以要先截取,流就变成了固定长度,程序就可以结束了。