Stream 流
是数据渠道,用于操作数据源(集合,数组)等所生成的元素序列。
① Stream 自己不会存储元素。
② Stream 不会改变源对象。会返回一个持有结果的新Stream.
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
一、Stream的三个操作步骤:
//1.可以通过Collection系列集合提供的Stream() 或 parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//2.通过Arrays 中的静态方法 stream() 获取数组流
String[] str = new String[10];
Stream<String> stream1 = Arrays.stream(str);
//3.通过Stream类中的静态方法 of
Stream<String> stream2 = Stream.of("aa", "bb", "cc");
//4.创建无线流
//迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
//生成
Stream.generate(() -> new Random().nextInt());
–筛选与切片
/*
* 筛选与切片
* filter -- 接收Lambda,从流中排除某些元素
* limit -- 截断流,使其元素不超过指定数量
* skip(n) --跳过元素,返回一个跳过了前 n 个元素的流。若流中元素不足n个,则返回一个空流,与limit互补
* distinct -- 筛选,通过流所生成的 hashCode 和 equals() 去重
*
* */
List<String> lists = Arrays.asList(("123"),
("456"),
("789"),
("123"),
("456"));
//过滤掉长度不大于2的,限制4个,也就是把第二个456去掉了。跳过2个,就是789,123
lists.stream()
.filter((x) -> x.length() > 2)
.limit(4)
.skip(2)
.forEach(System.out::println);
//全部去重,123,456,789
lists.stream().distinct().forEach(System.out::println);
–映射
public static void main(String[] args) {
/**
* 映射
* map--接收lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素
*
*/
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);
/**
* flatMap --接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
* */
//流中流
Stream<Stream<Character>> stream = list.stream().map(
TestStreamAPI2::filterChartater
);
stream.forEach((sm) -> sm.forEach(System.out::println));
//使用flatMap
Stream<Character> streams = list.stream().flatMap(TestStreamAPI2::filterChartater);
streams.forEach(System.out::println);
}
static Stream<Character> filterChartater(String str) {
List<Character> lists = new ArrayList<>();
for (Character c : str.toCharArray()) {
lists.add(c);
}
return lists.stream();
}
–排序
//排序
//自然排序: sorted()
List<String> list = Arrays.asList("ddd", "bbb", "aaa", "ccc");
list.stream().sorted().forEach(System.out::println);
//定制排序: sorted(Comparator com)
list.stream().sorted(
(e1,e2)->{
int i = e2.compareTo(e1);
return i;
}
).forEach(System.out::println);
–查找与匹配
/**
* 查找与匹配
*
* allMatch --检查是否匹配所有元素
* anyMatch --任意一个
* noneMatch --没有匹配
*
* */
boolean allMatch = list.stream().allMatch((x) -> x.equals("aaa"));
boolean anyMatch = list.stream().anyMatch((x) -> x.equals("aaa"));
boolean noneMatch = list.stream().noneMatch((x) -> x.equals("aaa"));
System.out.println(allMatch + "," + anyMatch + "," + noneMatch);
/*
* findFirst --返回第一个元素
* findAny --返回当前流中的任意元素.经验证,并不随机。待研究。
*/
Optional<String> first = list.stream().findFirst();
Optional<String> any = list.parallelStream().findAny();
System.out.println("first:" + first.get() + ",any:" + any.get());
/*
* count --总个数
* max--最大值
* min --最小值
*/
long count = list.stream().count();
Optional<String> max = list.stream().max(String::compareTo);
Optional<String> min = list.stream().min(String::compareTo);
System.out.println("count:"+count+",max:"+max.get()+",min:"+min.get());
–规约与收集
List<String> list = Arrays.asList("ddd", "bbb", "aaa", "ccc");
List<Integer> lists = Arrays.asList(1,2,3,4,5);
/**
* 规约
*
* reduce(T identity,BinaryOperator)/reduce(BinaryOperator)
* --可以将流中元素反复结合起来,得到一个值
*
* */
List<Integer> lists = Arrays.asList(1,2,3,4,5);
//起始值 为0,即0作为x,1作y,得到的返回值再作x,再加2...
Integer reduce = lists.stream().reduce(0, (x, y) -> x + y);
System.out.println(reduce);
/**
* 收集:
* Collect-将流转换为其他形式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
* */
List<String> listss = list.stream().collect(Collectors.toList());
Set<String> sets = list.stream().collect(Collectors.toSet());
HashSet<String> hashSet = list.stream().collect(Collectors.toCollection(HashSet::new));
//总数
Long collect = lists.stream().collect(Collectors.counting());
//平均
Double collect2 = lists.stream().collect(Collectors.averagingInt(Integer::intValue));
//总和
Integer collect1 = lists.stream().collect(Collectors.summingInt(Integer::intValue));
System.out.println(collect+","+collect1+","+collect2);
//最大值
//最小值
......
–功能API还有很多,可以自己尝试。这里不多赘述了。
并行流与顺序流
并行流就是把一个内容分成多个数据块,并有不同的线程分别处理每个数据块的流。
JAVA8 中将并行进行了优化,我们可以很容易的对数据进行操作。StreamAPI 可以声明性的通过
parallel() 与 sequential() 在并行流和顺序流 之间进行切换。
fork join式 并行。拆分合并充分利用cpu
// 执行时间373
Instant start = Instant.now();
long reduce1 = LongStream.rangeClosed(0, 1000000000L)
.reduce(0, Long::sum);
Instant end = Instant.now();
System.out.println(Duration.between(start,end).toMillis());
//并行 执行时间106
Instant start2 = Instant.now();
long reduce2 = LongStream.rangeClosed(0, 1000000000L)
.parallel()
.reduce(0, Long::sum);
Instant end2 = Instant.now();
System.out.println(Duration.between(start2,end2).toMillis());
//切换回顺序 3361
Instant start3 = Instant.now();
long reduce3 = LongStream.rangeClosed(0, 1000000000L)
.sequential()
.reduce(0, Long::sum);
Instant end3 = Instant.now();
System.out.println(Duration.between(start3,end3).toMillis());