之前大部分时间使用的jdk7进行编程, 进入新公司后开始大量使用jdk8,一些新的特性之前多是了解学习过,没有实际的的使用经验,现在对最近的使用的感悟做下总结。
1 流式编程是什么?
Java8以前我们常用的编程范式是命令式编程,使用起来比较复杂和繁琐,所以老是有很多新语言标榜自己的简单明了,强调Java的笨重,现在Java也加入了函数式编程,是代码看起来更加简洁与灵活,java流式编程主要操作对象是集合,为集合添加了查找、过滤、分组、排序等一系列的增强操作,使用起来更加方便。
2 核心stream()
“Stream流”其实是一个集合元素的函数模型,它不是集合,也不是数据结构,其本身并不存储任何元素,它的使用模式是先对需要进行的中间操作进行模型拼装,等到出现真正执行的方法类型于count(),collect()等终极操作时才进行整体的执行。先规划,后执行。
3 获取流的方式
1.根据Collection获取流
java.util.Collection 接口中加入了默认方法default stream 用来获取流,所以其所有实现类均可获取流
List list = new ArrayList<>();
Stream st1 = list.stream();
Set set = new HashSet<>();
Stream st2 = set.stream();
Vector vector = new Vector<>();
Stream st3 = vector.stream();
2.根据Map获取流
java.util.Map 接口不是 Collection 的子接口,且其K-V数据结构不符合流元素的单一特征,所以获取对应的流需要分key、value或entry等情况
Map<String,String> map = new HashMap<>();
Stream keyStream = map.keySet().stream();
Stream valueStream = map.values().stream();
Stream<Map.Entry<String,String>> entryStream = map.entrySet().stream();
3.根据数组获取流
String[] array = {“1”,“2”,“3”,“4”};
Stream st1 = Stream.of(array);
4 常用的操作
stream() − 为集合创建串行流。
new ArrayList().stream();
parallelStream() − 为集合创建并行流。
## new ArrayList().parallelStream();
forEach() - Stream 提供了新的方法 ‘forEach’ 来迭代流中的每个数据。
new ArrayList().forEach(System.out::println)
map() - map 方法用于映射每个元素到对应的结果
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
filter() - filter 方法用于通过设置的条件过滤出元素。
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
limit() - limit 方法用于获取指定数量的流。
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
sorted() - sorted 方法用于对流进行排序。
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
Collectors() - Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
统计相关
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());
skip(long n) - 跳过前几个元素
Stream.of("1", "2", "3", "4", "5", "6")
.skip(5)
.forEach(System.out::println);
``
distinct() - 去掉集合中的重复元素
list.stream().map(a::getId()).distinct().collect(Collectors.toList());
findFirst() - 获取集合第一个元素
list.stream().findFirst()
findAny() - 获取集合中任意一个元素
list.stream().findFirst()
Fork/Join框架
Stream的并行模式使用了Fork/Join框架,Fork/Join框架是java7中加入的一个并行任务框架,可以将任务拆分为多个小任务,每个小任务执行完的结果在合并成为一个结果。在任务的执行过程中使用工作窃取(work-stealing)算法,减少线程之间的竞争。
效率问题
Stream和for循环相比 还是for循环效率高一点,stream更简洁方便,这个看实际情况自由取舍