一.流(Stream)到底是什么?
是数据渠道,用于操作数据源(集合、数组等)所生成元素
的序列。
“集合讲的是数据,流讲的是计算”
注意:
1.Stream自己不会存储元素。
2.Stream不会改变源对象。相反,他们会返回一个持有
新结果的Stream。
3.Stream操作是延迟执行的。这意味它们会等到需要
结果的时候执行。
二.Stream 的三个操作步骤
1.创建Stream
public class TestStreamAPI {
//创建Stream
@Test
public void test1(){
/*
1.可以通过Collection 系列集合提供的Stream()
或parallelStream(),Stream()产生的是串行流,
parallelStream()产生的是并行流。
*/
List<String> list=new ArrayList<>();
Stream<String> stream = list.stream();
//2.通过Arrays 中的静态方法stream()获取数组流
Employee[] emps=new Employee[10];
Stream<Employee> stream1 = Arrays.stream(emps);
//3.通过Stream 类中的静态方法of()
Stream<String> stream2 = Stream.of("a", "b", "c");
//4.创建无限流
//迭代
Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2);
//生成
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);
}
}
2.中间操作
public class TestStreamAPI2 {
private List<Employee> employees=Arrays.asList(
new Employee("张三",18,999.99),
new Employee("李四",38,555.55),
new Employee("王五",50,444.44),
new Employee("赵六",16,333.33),
new Employee("田七",8,222.22),
new Employee("田七",8,222.22),
new Employee("田七",8,222.22)
);
//中间操作
/*
* 筛选与切片
* filter----接收Lambda,从流中排除某些元素
* limit---截断流,使其元素不超过给定数量
* skip(n)---跳过,返回一个扔掉了前n个元素的流。若流中元素不满n个,则返回一个空流。与limit互补。
* distinct---筛选,通过流所生成的hashcode()和equals()去除重复元素
*
* 排序
* sorted()---自然排序(Comparable)
* sorted(Comparator com)---定制排序(Comparator)
*
*/
//filter----接收Lambda,从流中排除某些元素
@Test
public void test1(){
//中间操作,不会执行任何操作。
Stream<Employee> stream = this.employees.stream()
.filter((e) -> {
System.out.println("Stream API中间操作");
return e.getAge() > 35;
}
);
//终止操作,一次性执行全部内容,即“惰性求值”
stream.forEach(System.out::println);
}
//内部迭代,迭代操作由StreamAPI完成
@Test
public void test2(){
//这是外部迭代
Iterator<Employee> iterator = this.employees.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
//limit---截断流,使其元素不超过给定数量,注意在截断了指定的元素后就不会往下迭代了
@Test
public void test3() {
this.employees.stream()
.filter((e) ->
{
System.out.println("短路操作");
return e.getSalary() > 200;
})
.limit(2)
.forEach(System.out::println);
}
//skip(n)---跳过,返回一个扔掉了前n个元素的流。若流中元素不满n个,则返回一个空流。与limit互补。
@Test
public void test4(){
this.employees.stream()
.filter((e)->e.getSalary()>200)
.skip(2)
.forEach(System.out::println);
}
//distinct---筛选,通过流所生成的hashcode()和equals()去除重复元素
@Test
public void test5(){
this.employees.stream()
.filter((e)->e.getSalary()>200)
.skip(2)
.distinct()
.forEach(System.out::println);
}
/*
* sorted()---自然排序(Comparable)
* sorted(Comparator com)---定制排序(Comparator)
*/
@Test
public void test6(){
List<String> list=Arrays.asList("b","a","c");
list.stream()
.sorted()
.forEach(System.out::println);
System.out.println("**************");
this.employees.stream()
.sorted((e1,e2)->{
if(e1.getAge().equals(e2.getAge())){
return e1.getSalary().compareTo(e2.getSalary());
}
return e1.getAge().compareTo(e2.getAge());
})
.forEach(System.out::println);
}
}
public class TestStreamAPI3 {
private List<Employee> employees=Arrays.asList(
new Employee("张三",18,999.99),
new Employee("李四",38,555.55),
new Employee("王五",50,444.44),
new Employee("赵六",16,333.33),
new Employee("田七",8,222.22),
new Employee("田七",8,222.22),
new Employee("田七",8,222.22)
);
/*
* 映射
* map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其
* 映射成一个新的元素。
* flatMap---接收一个函数作为参数,流中的每个值都换成另一个流,然后把所有流连城一个流
*/
@Test
public void test1(){
Arrays.stream(new String[]{"aa","bb","cc"})
.map((str)->str.toUpperCase())
.forEach(System.out::println);
System.out.println("******************");
this.employees.stream()
.map(Employee::getName)
.distinct()
.forEach(System.out::println);
System.out.println("******************");
Stream<Stream<Character>> stream = Arrays.stream(new String[]{"aa", "bb", "cc"})
.map(TestStreamAPI3::filterCharacter);
stream.forEach((s)->s.forEach(System.out::println));
System.out.println("******************");
//flatMap
Arrays.stream(new String[]{"aa", "bb", "cc"})
.flatMap(TestStreamAPI3::filterCharacter)
.forEach(System.out::println);
}
public static Stream<Character> filterCharacter(String str){
List<Character> characterList=new ArrayList<>();
for (Character character : str.toCharArray()) {
characterList.add(character);
}
return characterList.stream();
}
}
3.终止操作(终端操作)
public class TestStreamAPI4 {
/*
* 查找与匹配
* allMatch-检查是否匹配所有元素
* anyMatch-检查是否至少匹配一个元素
* noneMatch-检查是否没有匹配
* findFirst-返回第一个元素
* findAny-返回当前流中中的任意元素
* count-返回流中元素的总个数
* max-返回流中最大值
* min-返回流中最小值
*/
private List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 999.99, Employee.Status.FREE),
new Employee("李四", 38, 555.55, Employee.Status.BUSY),
new Employee("王五", 50, 444.44, Employee.Status.VOCATION),
new Employee("赵六", 16, 333.33, Employee.Status.FREE),
new Employee("田七", 8, 222.22, Employee.Status.BUSY)
);
@Test
public void test1() {
boolean flag = employees.stream()
.anyMatch(e -> e.getStatus() == Employee.Status.BUSY);
System.out.println(flag);
flag = employees.stream().
allMatch(e -> e.getStatus() == Employee.Status.BUSY);
System.out.println(flag);
flag = employees.stream().
noneMatch(e -> e.getStatus() == Employee.Status.BUSY);
System.out.println(flag);
Optional<Employee> op = employees.stream()
.sorted(Comparator.comparingDouble(Employee::getSalary))
.findFirst();
System.out.println(op.get());
Optional<Employee> any = employees.parallelStream()
.filter((e) -> e.getStatus() == Employee.Status.FREE)
.findAny();
System.out.println(any.get());
long count = employees.stream()
.count();
System.out.println(count);
Optional<Employee> max = employees.stream()
.max(Comparator.comparingDouble(Employee::getSalary));
System.out.println(max.get());
Optional<Double> min = employees.stream()
.map(Employee::getSalary)
.min(Double::compareTo);
System.out.println(min.get());
}
/*
* 归约
* reduce(T identity ,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来,得到一个值
*/
@Test
public void test01() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Integer reduce = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println(reduce);
System.out.println("**************");
Optional<Double> reduce1 = employees.stream()
.map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(reduce1.get());
}
/*
* 收集
* collection-将流转为其它形式。接收一个collection接口实现,用于Stream中元素做汇总的方法
*/
@Test
public void test03() {
List<String> collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
System.out.println(collect);
System.out.println("***********************");
HashSet<String> hashSet = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));
System.out.println(hashSet);
System.out.println("******************");
//总数
Long value = employees.stream()
.collect(Collectors.counting());
System.out.println("总数"+value);
//平均值
Double aDouble = employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println("工涨平均值:"+aDouble);
//总和
Double aDouble1 = employees.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println("工涨总和:"+aDouble1);
//最大值
Optional<Employee> collect1 = employees.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println("工涨最大值:"+collect1.get());
//分组
Map<Employee.Status, List<Employee>> collect2 = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(collect2);
//多级分组
Map<Employee.Status, Map<String, List<Employee>>> collect3 = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(
(e) -> {
if (((Employee) e).getAge() <= 35) {
return "青年";
}
if (((Employee) e).getAge() <= 50) {
return "中年";
}
return "老年";
}
)));
System.out.println(collect3);
//分片
Map<Boolean, List<Employee>> collect4 = employees.stream()
.collect(Collectors.partitioningBy(e -> e.getSalary() > 800));
System.out.println(collect4);
System.out.println("********************");
DoubleSummaryStatistics collect5 = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(collect5.getCount());
System.out.println("**********************");
//连接字符串
String collect6 = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(",", "prefix", "suffix"));
System.out.println(collect6);
}
}