Stream API说明
为什么使用Stream API
什么是Stream
操作三步骤
创建Stream
方式一:集合
方式二:数组
方式三:Stream类的静态方法of()
方式四:创建无限流(了解)
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class Test1 {
@Test
public void test1(){
List<Employee> list = new ArrayList<>();
list.add(new Employee("A",20,1000));
list.add(new Employee("B",15,2000));
list.add(new Employee("C",20,3000));
list.add(new Employee("D",15,500));
//返回一个顺序流
Stream<Employee> stream = list.stream();
//返回一个并行流
Stream<Employee> parallelStream = list.parallelStream();
}
@Test
public void test2(){
int[] arr = new int[]{1,2,3,4,5,6};
//Arrays静态方法返回一个流
IntStream intStream = Arrays.stream(arr);
Employee e1 = new Employee("E",20,1000);
Employee e2 = new Employee("F",18,500);
Employee[] arr2 = new Employee[]{e1,e2};
Stream<Employee> employeeStream = Arrays.stream(arr2);
}
@Test
public void test3(){
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
}
}
Stream的中间操作
筛选与切片
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class Test2 {
@Test
public void test1(){
//filter
List<Employee> list = new ArrayList<>();
list.add(new Employee("A",20,1000));
list.add(new Employee("B",15,2000));
list.add(new Employee("C",20,3000));
list.add(new Employee("D",15,500));
list.add(new Employee("E",20,2000));
Stream<Employee> stream = list.stream();
// forEach是终止操作,先拿来用,必须终止之后中间操作才有效果 forEach里面的consumer优先使用方法引用
//stream.filter(e -> e.getSalary() > 1000).forEach(employee -> System.out.println(employee));
stream.filter(e -> e.getSalary() > 1000).forEach(System.out::println);
System.out.println("================");
//此时stream已经被终止了 需要重新声明 只要前三个
Stream<Employee> stream2 = list.stream();
stream2.limit(3).forEach(System.out::println);
System.out.println("================");
//此时stream已经被终止了 需要重新声明 跳过前3个
Stream<Employee> stream3 = list.stream();
stream3.skip(3).forEach(System.out::println);
System.out.println("================");
//此时stream已经被终止了 需要重新声明 去重
list.add(new Employee("F",20,1000));
list.add(new Employee("F",20,1000));
list.add(new Employee("F",20,1000));
System.out.println("去重前");
for (Employee e : list){
System.out.println(e);
}
System.out.println("去重后");
list.stream().distinct().forEach(System.out::println);
}
}
Employee{name=‘B’, age=15, salary=2000}
Employee{name=‘C’, age=20, salary=3000}
Employee{name=‘E’, age=20, salary=2000}
================
Employee{name=‘A’, age=20, salary=1000}
Employee{name=‘B’, age=15, salary=2000}
Employee{name=‘C’, age=20, salary=3000}
================
Employee{name=‘D’, age=15, salary=500}
Employee{name=‘E’, age=20, salary=2000}
================
去重前
Employee{name=‘A’, age=20, salary=1000}
Employee{name=‘B’, age=15, salary=2000}
Employee{name=‘C’, age=20, salary=3000}
Employee{name=‘D’, age=15, salary=500}
Employee{name=‘E’, age=20, salary=2000}
Employee{name=‘F’, age=20, salary=1000}
Employee{name=‘F’, age=20, salary=1000}
Employee{name=‘F’, age=20, salary=1000}
去重后
Employee{name=‘A’, age=20, salary=1000}
Employee{name=‘B’, age=15, salary=2000}
Employee{name=‘C’, age=20, salary=3000}
Employee{name=‘D’, age=15, salary=500}
Employee{name=‘E’, age=20, salary=2000}
Employee{name=‘F’, age=20, salary=1000}
Stream的中间操作
映射
考察flatmap先考察这个
那么map就类似add,flagmap就类似addAll。
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Test3 {
@Test
public void test(){
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
//list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
list.stream().map(String::toUpperCase).forEach(System.out::println);
System.out.println("========================================");
//获取工资大于1000的员工的工资
List<Employee> list2 = new ArrayList<>();
list2.add(new Employee("A",20,1000));
list2.add(new Employee("B",15,2000));
list2.add(new Employee("C",20,3000));
list2.add(new Employee("D",15,500));
list2.add(new Employee("E",20,2000));
Stream<Employee> stream = list2.stream();
//employee的stream映射成integer的stream
Stream<Integer> integerStream = stream.map(Employee::getSalary);
integerStream.filter(s -> (s > 1000)).forEach(System.out::println);
System.out.println("=======================================");
}
public static Stream<Character> stringToCharacterStream(String s){
ArrayList<Character> list = new ArrayList<>();
for (Character c: s.toCharArray()){
list.add(c);
}
return list.stream();
}
@Test
public void test2(){
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
//list中一个元素返回一个stream
Stream<Stream<Character>> streamStream = list.stream().map(Test3::stringToCharacterStream);
streamStream.forEach(s -> {
s.forEach(System.out::println);
});
System.out.println("==================================");
Stream<Character> characterStream = list.stream().flatMap(Test3::stringToCharacterStream);
characterStream.forEach(System.out::println);
}
}
map如果把流中的每一个元素映射成一个流,并返回一个由流构成的流,进行forEach就必须两层,一层lambda表达式,一层方法引用,此时可以用flatMap把里面的流打开,形成一对多的映射,返回一个一层流。
Stream的中间操作
排序
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class Test4 {
@Test
public void test(){
List<Integer> list1 = Arrays.asList(123, 434, 54, 12, 1223, 50, 0);
list1.stream().sorted().forEach(System.out::println);
List<Employee> list = new ArrayList<>();
list.add(new Employee("A",20,1000));
list.add(new Employee("B",15,2000));
list.add(new Employee("C",20,3000));
list.add(new Employee("D",15,500));
list.add(new Employee("E",20,2000));
list.stream().sorted(Comparator.comparingInt(Employee::getSalary).thenComparing(Employee::getAge)).forEach(System.out::println);
}
}
Stream的终止操作
匹配与查找
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class Test5 {
@Test
public void test(){
List<Employee> list = new ArrayList<>();
list.add(new Employee("A",20,1000));
list.add(new Employee("B",15,2000));
list.add(new Employee("C",20,3000));
list.add(new Employee("D",15,500));
list.add(new Employee("E",20,2000));
Stream<Employee> stream = list.stream();
System.out.println(stream.allMatch(e -> e.getAge() > 18));
Stream<Employee> stream1 = list.stream();
System.out.println(stream1.anyMatch(e -> e.getSalary() >2000));
Stream<Employee> stream2 = list.stream();
System.out.println(stream2.noneMatch(e->e.getSalary() > 3000));
Stream<Employee> stream3 = list.stream();
Optional<Employee> first = stream3.findFirst();
System.out.println(first);
Stream<Employee> stream4 = list.stream();
Optional<Employee> any = stream4.findAny();
System.out.println(any);
Stream<Employee> stream5 = list.stream();
System.out.println(stream5.count());
Stream<Employee> stream6 = list.stream();
System.out.println(stream6.max(Comparator.comparingInt(Employee::getSalary)));
Stream<Employee> stream7 = list.stream();
System.out.println(stream7.min(Comparator.comparingInt(Employee::getSalary)));
}
}
归约
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test6 {
@Test
public void test(){
List<Integer> list1 = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//第一个参数初始值
//System.out.println(list1.stream().reduce(0,(x,y)->x+y));
System.out.println(list1.stream().reduce(0,Integer::sum));
List<Employee> list = new ArrayList<>();
list.add(new Employee("A",20,1000));
list.add(new Employee("B",15,2000));
list.add(new Employee("C",20,3000));
list.add(new Employee("D",15,500));
list.add(new Employee("E",20,2000));
System.out.println(list.stream().map(Employee::getSalary).reduce(Integer::sum));
}
}
收集
收集也就是流转集合
package com.stream.xzc;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Test7 {
@Test
public void test(){
//查找工资大于1000的员工 结果返回一个List
List<Employee> list = new ArrayList<>();
list.add(new Employee("A",20,1000));
list.add(new Employee("B",15,2000));
list.add(new Employee("C",20,3000));
list.add(new Employee("D",15,500));
list.add(new Employee("E",20,2000));
List<Employee> collect = list.stream().filter(e -> e.getSalary() > 1000).collect(Collectors.toList());
System.out.println(collect);
}
}
Optional类
package com.optional.xzc;
import com.stream.xzc.Employee;
import java.util.Optional;
public class Test {
@org.junit.Test
public void test(){
Employee e = new Employee("hawkeye",10,1000);
Optional<Employee> o = Optional.of(e);
System.out.println(o);
Employee e1 = null;
Optional<Employee> o1 = Optional.ofNullable(e1);
System.out.println(o1);
Optional<Employee> o2 = Optional.empty();
System.out.println(o2);
}
}
Optional使用举例
新建一个Dog类和一个Person类
不用Optional类时,我们这样通过Person获得Dog的名字
public String getDogName(Person p){
if(p!=null){
Dog d = p.getDog();
if(d!=null){
return d.getName();
}
}
return null;
}
先看一下orElse方法的作用,形参就是一个备胎。
package com.optional.xzc;
import org.junit.Test;
import java.util.Optional;
public class Test2 {
@Test
public void test(){
Person p1 = new Person("p1",new Dog());
Person p2 = null;
Person p3 = new Person("p3",new Dog("p3's dog"));
Person p4 = new Person("p4",null);
System.out.println(getDogName(p1));
System.out.println(getDogName(p2));
System.out.println(getDogName(p3));
System.out.println(getDogName(p4));
}
public static String getDogName(Person p){
Optional<Person> optionalPerson = Optional.ofNullable(p);
Person hawkeye = optionalPerson.orElse(new Person("Hawkeye", new Dog("Hawkeye's dog")));
Optional<Dog> optionalDog = Optional.ofNullable(hawkeye.getDog());
Dog dog = optionalDog.orElse(new Dog("绝对非空的dog"));
return dog.getName();
}
}
p1人存在,也有狗,只不过狗是空参构造,所以没名字
p2人不存在,给了一个备胎 hawkeye,他有狗
p3人存在,也有狗,狗有名字
p4人存在,但狗指定为null,即不存在,走到了最后一层。
这里主要是注意使用orElse方法,使用get方法会抛异常。
get可以和of方法搭配,orElse和ofNullable搭配。
当然也可以用isPresent先判断是不是空。