首先,Stream流有一些特性:
1 .Stream流不是一种数据结构,不保存数据,它只是在原数据集上定义了一组操作。
2.这些操作是惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。
3.Stream不保存数据,故每个Stream流只能使用一次。
Stream 的操作分为三种:
1.创建stream流。
2.中间操作。
3.终止操作。
演示代码下载地址:https://github.com/prettyRain/java8demo.git
1.创建stream
- 1)Collection接口的stream()或parallelStream()方法
- 2)Arrays.stream(array)
- 3)静态的Stream.iterate()方法生成无限流,接受一个种子值以及一个迭代函数
- 4)静态的Stream.generate()方法生成无限流,接受一个不包含引元的函数
/**
* 创建 stream
*/
@Test
public void test1(){
//1.Collection提供了两个方法 stream() 和 parallelStream()
List<String> list = new ArrayList<String>();
Stream<String> stream = list.stream();
Stream<String> stringStream = list.parallelStream();
//2.通过Arrays中的stream()获取一个数组流
Integer[] nums = new Integer[10];
Stream<Integer> stream1 = Arrays.stream(nums);
//3.通过stream类中的静态方法 of()
Stream<Integer> stream2 = Stream.of(1,2,3,4,5);
//4.创建无限流
//迭代
Stream<Integer> stream3 = Stream.iterate(2,(x) -> x+2).limit(5);
stream3.forEach(System.out::println);
//生成 里面是供给型
Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
//里面是消费型
stream4.forEach(System.out::println);
}
2.中间操作:
切片和筛选:
- 1)filter——接收 Lambda , 从流中排除某些元素。
- 2)limit——截断流,使其元素不超过给定数量。
- 3)skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
- 4)distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
- 5)sorted()——自然排序
- 6)sorted(Comparator com)——定制排序
映射: - 1)map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
- 2)flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
public class TestStream2 {
Student[] aa = new Student[]{new Student(1L,"小明","男",18,new BigDecimal(5000)),
new Student(2L,"小花","女",12,new BigDecimal(6000)),
new Student(3L,"小李","男",10,new BigDecimal(3000)),
new Student(4L,"小刘","男",17,new BigDecimal(9000)),
new Student(5L,"小刚","男",13,new BigDecimal(8000))};
/**
* filter——接收 Lambda , 从流中排除某些元素。
* limit——截断流,使其元素不超过给定数量。
* skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
* distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
*/
//内部迭代
@Test
public void test1(){
//所有的中间操作不会做任何的处理
Stream<Student> stream = Arrays.stream(aa)
.filter((e) -> e.getAge() > 12l)
.limit(3)
.distinct()
.skip(1);
//只有当终止操作时,所有的操作才会一次性执行,称为“惰性求值”
stream.forEach(System.out::println);
}
/**
* map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
* flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
*/
@Test
public void test2(){
Stream<Student> studentStream = Arrays.stream(aa);
studentStream.map( (t) -> t.getName())
.forEach(System.out::println);
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
Stream<String> stream = strings.stream()
.map(String::toUpperCase);
stream.forEach(System.out::println);
//map流中有流
Stream<Stream<String>> stream1 = strings.stream()
.map(TestStream2::getstream);
stream1.forEach(xs -> xs.forEach(System.out::println));
//flatMap 把所有流连成一个流
Stream<String> stream2 = strings.stream()
.flatMap(TestStream2::getstream);
stream2.forEach(System.out::println);
}
public static Stream<String> getstream(String str){
List<String> list = new ArrayList<>();
char[] chars = str.toCharArray();
for(int i = 0 ; i < chars.length ; i++){
list.add(String.valueOf(chars[i]));
}
return list.stream();
}
/**
* sorted()——自然排序
* sorted(Comparator com)——定制排序
*/
@Test
public void test3(){
Stream<Student> stream = Arrays.stream(aa);
stream.map(x -> x.getName())
.sorted()
.forEach(System.out::println);
Arrays.stream(aa).sorted((x,y) -> {
if(x.getAge()==y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(),y.getAge());
}
})
.forEach(System.out::println);
}
}
3.终止操作
- 1) allMatch——检查是否匹配所有元素
- 2) anyMatch——检查是否至少匹配一个元素
- 3)noneMatch——检查是否没有匹配的元素 没有匹配返回true
- 4)findFirst——返回第一个元素
- 5)findAny——返回当前流中的任意元素
- 6)count——返回流中元素的总个数
- 7)max——返回流中最大值
- 8)min——返回流中最小值
- 9) reduce(T identity, BinaryOperator) / reduce(BinaryOperator)--规约可以将流中元素反复结合起来,得到一个值。
- 10)collect--收集 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
public class TestStream3 {
public List<Student> bb = Arrays.asList(new Student(1L,"小明","男",18,new BigDecimal(5000)),
new Student(2L,"小花","女",17,new BigDecimal(6000)),
new Student(3L,"小李","男",10,new BigDecimal(3000)),
new Student(4L,"小刘","男",17,new BigDecimal(9000)),
new Student(5L,"小刚","男",13,new BigDecimal(8000)));
/**
* allMatch/anyMatch/noneMatch/findFirst/findAny/count/max/min
*/
@Test
public void test1(){
boolean b = bb.stream()
.allMatch(x -> x.getAge() == 12);
System.out.println(b);
boolean b1 = bb.stream()
.anyMatch(x -> x.getAge() == 12);
System.out.println(b1);
boolean b2 = bb.stream()
.noneMatch(x -> x.getAge() == 19);
System.out.println(b2);
Optional<Student> first = bb.stream()
.sorted((x, y) -> x.getAge().compareTo(y.getAge()))
.findFirst();
System.out.println(first.get());
Optional<Student> any = bb.stream()
.filter(x -> x.getPrice().compareTo(BigDecimal.valueOf(5000)) > 0)
.findAny();
System.out.println(any.get());
long count = bb.stream()
.filter(x -> x.getPrice().compareTo(BigDecimal.valueOf(5000)) > 0)
.count();
System.out.println(count);
Optional<Integer> max = bb.stream()
.map(Student::getAge)
.max((x, y) -> x.compareTo(y));
System.out.println(max);
Optional<Student> min = bb.stream()
.min((x, y) -> x.getAge().compareTo(y.getAge()));
System.out.println(min.get());
}
/**
* reduce 归约
*/
@Test
public void test2(){
//从零开始加
Integer ages = bb.stream()
.map(Student::getAge)
.reduce(0, (x, y) -> x + y);
System.out.println(ages);
//没有初始的数
Optional<Integer> reduce = bb.stream()
.map(Student::getAge)
.reduce((x, y) -> x + y);
System.out.println(reduce.get());
}
/**
* collect
* 返回集合
*/
@Test
public void test3(){
List<Integer> collect = bb.stream()
.map(Student::getAge)
.collect(Collectors.toList());
collect.forEach(System.out::println);
Map<String, BigDecimal> collect1 = bb.stream()
.collect(Collectors.toMap(x -> x.getName(), x -> x.getPrice()));
Set<Map.Entry<String,BigDecimal>> entrySet = collect1.entrySet();
for(Map.Entry<String,BigDecimal> entry:entrySet){
System.out.println(entry.getKey()+"=="+entry.getValue());
}
HashSet<Student> collect2 = bb.stream()
.collect(Collectors.toCollection(HashSet::new));
collect2.forEach(System.out::println);
}
/**
* collect
* 最大值 最小值 总和 平均值 总个数
*/
@Test
public void test4(){
Optional<BigDecimal> collect = bb.stream()
.map(Student::getPrice)
.collect(Collectors.minBy((x, y) -> x.compareTo(y)));
System.out.println(collect.get());
Optional<BigDecimal> collect1 = bb.stream()
.map(Student::getPrice)
.collect(Collectors.maxBy((x, y) -> x.compareTo(y)));
System.out.println(collect1.get());
Double collect3 = bb.stream()
.map(Student::getPrice)
.collect(Collectors.summingDouble(x -> Double.valueOf(x.toString())));
System.out.println(collect3);
Double collect4 = bb.stream()
.map(Student::getPrice)
.collect(Collectors.averagingDouble(x -> Double.valueOf(x.toString())));
System.out.println(collect4);
Long collect5 = bb.stream()
.collect(Collectors.counting());
System.out.println(collect5);
DoubleSummaryStatistics collect2 = bb.stream()
.map(Student::getPrice)
.collect(Collectors.summarizingDouble(x -> Double.valueOf(x.toString())));
System.out.println(collect2.getAverage());
System.out.println(collect2.getCount());
System.out.println(collect2.getSum());
System.out.println(collect2.getMax());
System.out.println(collect2.getMin());
}
/**
* collect
* 分组
*/
@Test
public void test5(){
//分组
Map<Integer, List<Student>> collect = bb.stream()
.collect(Collectors.groupingBy((e) -> e.getAge()));
for(Map.Entry<Integer,List<Student>> entry: collect.entrySet()){
System.out.println("分组的key"+entry.getKey());
entry.getValue().forEach(System.out::println);
}
//多级分组
Map<Integer, Map<BigDecimal, List<Student>>> collect1 = bb.stream()
.collect(Collectors.groupingBy(e -> e.getAge(), Collectors.groupingBy(e -> e.getPrice())));
System.out.println(collect1);
}
/**
* collect
* 分区
*/
@Test
public void test6(){
Map<Boolean, List<Student>> collect = bb.stream()
.collect(Collectors.partitioningBy((e) -> e.getAge() > 12));
for(Map.Entry<Boolean,List<Student>> entry : collect.entrySet()){
System.out.println("分组的key"+entry.getKey());
entry.getValue().forEach(System.out::println);
}
}
/**
* collect
* join
*/
@Test
public void test7(){
String collect = bb.stream()
.map(Student::getName)
.collect(Collectors.joining(",", "开始--", "--结束"));
System.out.println(collect);
}
}