Stream流
作用:
主要和函数式接口以及Lambda表达式配合处理集合数据
Stream就相当于一条流水线,数据就是产品,当产品从传送带头传下来,多个工人按照顺序对产品进行加工,最后得到成品。
几种创建方式
基于数组创建流
int[] a = new int[]{1, 2, 3, 4};
IntStream s = Arrays.stream(a);
Stream<String> s2 = Stream.of("h", "e", "l", "l", "o");
基于生成器创建流
Stream.Builder builder= Stream.builder();
Stream<String> stream= builder.add("hello").add("world").build();
stream.forEach(System.out::println);
基于集合创建流
流也分为串行流和并行流,并行流会将一个集合分成多个部分同步时处理,速度更快,但是废内存,同时处理数据的顺序是杂序,比如打印1-100,就不是按照顺序。
List<Integer> list=new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
//创建串行流
Stream<Integer> stream=list.stream();
//创建并行流
Stream<Integer> stream1=list.parallelStream();
基于函数创建流
Stream<Double> stream=Stream.generate(()->Math.random());
流的使用
/**
* filter过滤器的使用
*/
@Test
public void filterTest() {
List<Integer> list = Arrays.asList(7, 8, 5, 6, 4);
list.stream().filter(x -> x > 6).forEach(System.out::println);
}
/**
* 去重
*/
@Test
public void distinctTest() {
List<? extends Number> list = Arrays.asList(1, 1, 2, 5, 5, 6, 7);
Stream<? extends Number> distinctList = list.stream().distinct();
distinctList.forEach(System.out::println);
}
/**
* 返回从头到尾指定个数
*/
@Test
public void limitTest() {
List<? extends Number> list = Arrays.asList(1, 1, 2, 5, 5, 6, 7);
Stream<? extends Number> limitList = list.stream().limit(3);
limitList.forEach(System.out::println);
}
/**
* 跳过指定数量元素,截取后面元素
*/
@Test
public void skipTest() {
List<? extends Number> list = Arrays.asList(1, 1, 2, 5, 5, 6, 7);
Stream<? extends Number> skipList = list.stream().skip(2);
skipList.forEach(System.out::println);
}
@Test
public void FindTest() {
List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
// 遍历输出符合条件的元素
list.stream().filter(x -> x > 6).forEach(System.out::println);
// 匹配第一个
Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
// 匹配任意(适用于并行流)
Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
// 是否包含符合特定条件的元素
boolean anyMatch = list.stream().anyMatch(x -> x > 6);
System.out.println("匹配第一个值:" + findFirst.get());
System.out.println("匹配任意一个值:" + findAny.get());
System.out.println("是否存在大于6的值:" + anyMatch);
}
@Test
void mapTest() {
Stream.of("a", "aa", "aaaa")
.map(String::trim)//去掉空格
.map(String::toUpperCase)//变大写
.forEach(System.out::println);//打印
}
/**
* 将集合转换为相应元素长度的集合
*/
@Test
void mapTestTwo() {
List<String> list = Arrays.asList("what", "are", "you", "doing");
Stream<Integer> integerStream = list.stream().map(String::length);
integerStream.forEach(System.out::println);
}
/**
* 取出字符串长度大于2的字符串
*/
@Test
void listStreamList() {
List<String> listStream = Arrays.asList("i", "don't", "wanna", "see", "you", "anymore");
List<String> collect = listStream.stream().filter(x -> x.length() > 2).collect(Collectors.toList());
collect.forEach(System.out::println);
}
@Test
void empList(){
List<Emp> list = new ArrayList<>();
list.add(new Emp(331100,"thanos","manager",7788,new Date(2022,10,1),3000.0,2000.0,6869));
list.add(new Emp(331100,"yaso","manager",7788,new Date(2022,10,1),3000.0,2000.0,6869));
list.add(new Emp(331100,"cruis","manager",7788,new Date(2022,10,1),3000.0,2000.0,6869));
list.add(new Emp(331100,"anna","manager",7788,new Date(2022,10,1),3000.0,2000.0,6869));
//计算人数
Long countCollect = list.stream().collect(Collectors.counting());
//计算平均工资
Collector<Emp, ?, Double> empDoubleCollector = Collectors.averagingDouble(Emp::getSal);
//得出奖金最高数
list.stream().map(Emp::getComm).collect(Collectors.maxBy(Double::compare));
}
}
总结:
stream主要用于处理集合中的数据,由于它每次处理后返回的仍然是一个stream,所以很方便对数据进行链式操作,比如filter后又map。在流水线上,map和filter就相当于处理产品的工人,需要注意的是,流处理并不会改变原来集合中的数据,它相当于复制一份数据进行流水线处理。
而且stream是一次性的,刘翔流水一样,流火一次就会消失,不能进行二次处理,我们需要使用collect(collections.to(map,list…))方法将其收集起来。非常重要。