Java 8 数据流Stream的基本使用
来源:互联网 发布:淘宝无线端首页尺寸 编辑:程序博客网 时间:2024/06/05 00:48
数据流(Stream)的使用
1) Stream 的获取
① 通过集合Collection获取
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5));
Stream<Integer> stream = list.stream();
② 通过数组获取
String[] array = {"are","you","ok"};
Stream<String> stream = Array.stream(array);
//对于基本类型数组的处理
int[] array = {1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(array).boxed(); //此时Arrays.stream(array)获取的是一个IntStream对象
③ 通过值获取(尽量使用以上2种方式获取,这种方式存在缺陷)
Stream<String> stream = Stream.of("are","you","ok");
2) 筛选 filter
filter函数接收一个Lambda表达式作为参数,该表达式返回boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为true的元素;
//筛选出列表中的非空项
List<String> list = Arrays.asList("are","you","","ok");
List<String> filted = list.stream()
.filter(x-> !x.empty())
.collect(Collectors.toList());
3) 去重 distinct
List<String> list = Arrays.asList("are","you","you","ok");
List<String> distincted = list.stream()
.distinct()
.collect(Collectors.toList());
4) 截取 limit
截取流的前N个元素:
List<String> list = Arrays.asList("are","you","fucking","ok");
List<String> distincted = list.stream()
.limit(3);
.collect(Collectors.toList());
5) 跳过 skip
跳过流的前n个元素:
List<String> list = Arrays.asList("are","you","fucking","ok");
List<String> distincted = list.stream()
.skip(2);
.collect(Collectors.toList());
6) 映射 map
对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。
如:将 list 中每一个 Integer类型元素自增后转化为 String类型
List<Integer> list = Arrays.asList(1,2,3,4,5);
List<String> result = list.stream()
.map(x->String.valueOf(++x))
.collect(Collectors.toList());
7) 合并多个流 flatMap
List<String> list1 = .....
List<String> list2 = ...
List<List<String>> list = Arrays.asList(list1,list2);
//将list中的list1,list2合并为一个List<String>
List<String> listsum = list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
List<String> list = new ArrayList<String>();
list.add("I am a boy");
list.add("I love the girl");
list.add("But the girl loves another girl");
list.stream().map(line->line.split(" ")) //将每一个项分词,并映射为数组
.flatMap(Arrays::stream) //将每一个分项数组组合并到主流中,形成一个包含所有分项数组的总数组流
.distinct(); //去重
.forEach(System.out::println); //打印
8)匹配元素
anyMatch用于判断流中是否存在至少一个元素满足指定的条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
//判断流中是否含有>10的项
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
boolean result = list.stream()
.anyMatch(x->x>10);
allMatch用于判断流中的所有元素是否都满足指定条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
如,判断是否所有人都是学生:
//判断流中是否全部>5
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
boolean result = list.stream()
.allMatch(x->x>5);
noneMatch与allMatch恰恰相反,它用于判断流中的所有元素是否都不满足指定条件:
//判断流中是否 全部不满足 >5
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
boolean result = list.stream()
.noneMatch(x->x>5);
9)获取元素
findAny从流中随机选出 一个元素出来,它返回一个Optional类型的元素。
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Optional<Integer> result = list.stream().findAny();
if(result.isPresent())
Integer randValue = result.get();
//or:
Integer randValue = result.orElse(0);
//合并的调用方式
Integer randValue = list.stream().findAny().orElse(0);
Optional<Integer> result = list.stream().findFirst();
Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:
- isPresent()
判断容器中是否有值。 - ifPresent(Consume lambda)
容器若不为空则执行括号中的Lambda表达式。 - T get()
获取容器中的元素,若容器为空则抛出NoSuchElement异常。 - T orElse(T other)
获取容器中的元素,若容器为空则返回括号中的默认值。
10) 归约统计(基于数值流)
归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出。
在流中,可以将流装载如相应的 SummaryStatistics 来实现该功能
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
int max = stats.getMax()); //获取最大值
int min = stats.getMin()); //获取最小值
double sum = stats.getSum()); //获取总值
double avg = stats.getAverage()); //获取平均值
11) 遍历流 forEach
数据流提供了新的forEach方法遍历该流中的每个元素,方法参数为一个Lambda表达式,用于对每一个遍历的元素执行的操作;
//输出10个随机数
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
12) 排序 sorted
sorted方法用来流排序,默认升序排布,可以使用一个 Comparator 作为参数来实现自定义排序;
//输出10个排序好的随机数
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
13)parallelStream 并行处理
parallelStream是流 进行并行处理的替代方案。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
数值流的使用
采用Stream 的 redure 方法 进行数值归约操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低;
当流操作为纯数值操作时,使用数值流能获得较高的效率;
StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream;
1)将 Stream 转换成数值流
StreamAPI 提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong(参数:相应的转化Lambda表达式);
将数值流转化为Stream 的方法:boxed;
List<Double> list = Arrays.asList(2.3,2.4,2.5,2.7,2.8);
//普通Stream转为数值Stream
DoubleStream doubles = list.stream().mapToDouble(x->x); //转化为DoubleStream
IntStream ints = list.stream().mapToInt(x->Integer.parseInt(String.format("%.0f",x))); //转化为IntStream,同时进行取舍操作
//数值Stream转为普通Stream
Stream stream = list.boxed();
2)数值流的数值计算
每种数值流都提供了数值计算函数,如max、min、sum、avg等。
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
OptionalInt max = list.stream().max();
int max_value = max.orElse(0);
OptionalInt sum = list.steam().sum();
iny sum_value = sum.orElse(0);
由于数值流可能为空,并且给空的数值流计算最大值是没有意义的,因此max函数返回OptionalInt,它是Optional的一个子类,能够判断流是否为空,并对流为空的情况作相应的处理。
此外,mapToInt、mapToDouble、mapToLong进行数值操作后的返回结果分别为:OptionalInt、OptionalDouble、OptionalLong
Stream转换为Collection
//普通转换
Stream<String> stream = Arrays.stream("are","you","ok");
String[] array = stream().toArray();
//涉及拆箱、装箱操作的转换
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
int[] array = stream.mapToInt(x->x).toArray();
List<Integer> list1 = stream.collect(Collectors.toList());
List<Integer> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set<Integer> set = stream.collect(Collectors.toCollection(Set::new));
Stack<Integer> stack = stream.collect(Collectors.toCollection(Stack::new));