Powerful Stream API
1. Descrição da Stream API
-
As duas mudanças mais importantes no Java 8 são expressões Lambda e API Stream.
-
Stream API (java.util.stream) introduz o estilo de programação funcional real em Java, que é o melhor suplemento para a biblioteca de classes Java até agora, porque Stream API pode fornecer produtividade aos programadores Java e permitir que os programadores escrevam Produce mais eficiente, limpo código bonito e conciso.
-
Fluxo é um conceito chave para o processamento de coleções em Java 8. Ele pode especificar as operações que você deseja executar na coleção e pode executar operações muito complexas, como pesquisa, filtragem e mapeamento de dados. Usar o Stream API para operar na coleta de dados é semelhante a executar consultas de banco de dados em SQL. Você também pode usar a API Stream para operar em paralelo. Resumindo, a API Stram fornece uma maneira eficiente e fácil de usar para processar dados.
-
Bancos de dados persistentes, como Mysql, Oracle, etc., são equivalentes a operações de dados no nível de banco de dados, mas com o surgimento de bancos de dados NoSQL como MongDB e Radis, as operações de dados precisam ser realizadas no nível Java. Use Steam API neste momento
-
A diferença entre Stream e Collection: Collection é uma estrutura de memória estática. E o Stream é sobre computação. O primeiro é principalmente orientado para a memória e armazenado na memória, e o último é principalmente orientado para a CPU, e o cálculo é realizado através da CPU.
A coleção consiste em dados e o Stream trata de cálculos.
(1) O fluxo em si não armazena elementos.
(2) Fluxo não mudará o objeto de origem, em vez disso, eles retornarão um resultado retido para o novo Fluxo.
(3) As operações de fluxo são executadas com atraso, o que significa que esperarão até que os resultados sejam necessários antes da execução.
2. Criar fluxo (instanciar fluxo)
Uma fonte de dados (como: coleção, matriz), obtenha um fluxo
- Coleção Criar Fluxo
@Test
public void test(){
//获取一个集合
List<Employee> list = EmplpyeeData.getEmployees();
//default Stream<E> stream(); 返回一个顺序流
Stream<Employee> stream = list.stream();
//default Stream<E> parallelStream(); 返回一个并行流
Stream<Employee> parallelStream = list.parallelStream();
}
- Fluxo de criação de matriz
@Test
public void test(){
int[] arr = new int[]{
1,2,3,4,5,6};
//调用Arrays类的static<T> Stream<T> stream(T[] array);返回一个流
Instream stream = Arrays.stream(arr);
Employee e1 = new Employee("1001","Tom");
Employee e2 = new Employee("1002","Marry");
Employee[] arr1 = new Employee[]{
e1,e2};
Stream<Employee> stream1 = Arrays.stream(arr1);
}
- Criar fluxo por fluxo de ()
@Test
public void test(){
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
}
- Crie streams ilimitados (não comumente usados)
- Ajude-nos a usar ao criar dados
@Test
public void test(){
//迭代
//public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f);
//遍历前10个偶数(不会停下来)
Stream.iterate(0,t -> t + 2).forEach(System.out::println);
//加上限制,只要前十个偶数
Stream.iterate(0,t -> t + 2)limit(10).forEach(System.out::println);
//生成
//public static<T> Stream<T> generate(Supplier<T> s);
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
3. Operações intermediárias (filtragem, mapeamento, classificação)
Uma cadeia de operação intermediária para processar os dados da fonte de dados.
- Peneiramento e fatiamento
@Test
public void test(){
List<Employee> list = EmployeeData.getEmployees();
//filter(Predicate p) 接收 Lambda ,从流中排除某些元素
Stream<Employee> stream = list.stream();
//查询员工表中薪资>7000的员工信息
stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
//截断流 注意需要冲洗生成流,因为之前已经进行了终止操作
//是元素不超过给定的数量
list.stream().limit(3).forEach(System.out::println);
//skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个Null
list。stream().skip(20).forEach(System.out::println);
//distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
list.stream().distinct().forEach(System.out::println);
}
- Mapeamento
@Test
public void test13(){
List<String> list = Arrays.asList("abc","def","cbd","aaa");
//map(Function f) 接收一个函数作为参数,该函数提供了某种规则,通过这种规则将原有集合的数据映射到一个新的集合中。
list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
//练习:获取员工姓名大于三的员工姓名
List<Emplouyee> list = employeeData.getEmplyees();
//Stream<String> nameStream = list.stream.map(e -> e.getName());
Stream<String> nameStream = list.stream.map(Employee :: getName);
nameStream.filter(name ->name.length()>3).forEach(System.out::println);
}
@Test
public void test(){
//flatMap(Function f) 接受一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流。
//练习:
//集合里面套集合的情况时,遍历每一个元素。
//用map来做
//注意:StreamAPITest是类名,使用类名::静态方法
Stream<Stream<Charcator>> streamStream = list.stream().map(StreamAPITest :: fromStringtoStream);
streamStream.forEach(s ->{
s.forEach(System.out::println)
});
//用flatMap来做
Stream<Charactor> charactorStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
charactorStream.forEach(System.out::println);
}
public static Stream<Charcater> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for(Charactor c : str.toCharArray()){
list.add(c);
}
return list.stream();
}
- Organizar
@Test
public void test(){
//sorted() 自然排序
List<Integer> list = Arrays.asList(1,2412,3423,54,3234,645,1,212,-13,11);
list.stream().sorted().forEach(System.out::println);
//对象的排序,sorted(Comparator com) 定制排序
//需要实现接口
List<Employee> list = employeeData.getEmployees();
list.stream().sorted((e1,e2) -> {
int ageValue = Integer.compare(e1.getAge(),e2.getAge());
//按照年龄进行排序,如果年龄相等按照工资进行排序
if(ageValue != 0){
return ageValue;
}else{
return - Double.compare(e1.getSalary(),e2.getSalary());
}
}).forEach(System.out::println);
}
4. Terminar a operação (operação do terminal)
Uma vez que a operação de terminação é executada, a cadeia de operação intermediária é executada e o resultado é gerado, após o qual não será usado novamente. Se você quiser reutilizá-lo, você precisa recriar um fluxo
- Combine e encontre
List<Employee> list = EmployeeData.getEmployees();
//allMatch(Predicate p) 检查是否匹配所有元素
//练习:是否所有员工的年龄都大于18
boolean allMatch = list.stream().allMatch(e -> e.getAge() > 18);
//anyMatch(Predicate p) 检查是否至少匹配一个元素。
//练习:是否存在员工的工资大于10000
boolean anyMatch = list.stream().anyMatch(e -> e.getSalary() > 10000);
//noneMatch(Predicate p) 检查是否没有匹配的元素,有返回false,没有返回true
//练习:是否存在员工姓”雷“
boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startWitch("雷"));
//findFirst()返回第一个元素,可以结合排序来写
//findAny() 返回当前流中的任意元素
//count() 返回流中元素的总个数
long count = list.stream().filte(e -> e.getSalary() > 5000).count();
//max(Comparator c) 返回流中最大值
//练习 求员工中最高工资
//使用map先映射到工资...
Stream<Double> salaryStream = employees.stream().map(e - >e.getSalary());
Optional<Double> maxSalary = salarySaream.max(Double :: compare);
//min(Comparator c) 返回流中最小值
//求最低工资的员工信息
Optional<Employee> employee = list.stream().min((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary()));
//forEach(Cousumer c) 内部迭代
list.stream().forEach(System.out::println);
//注意与集合中的forEach()进行区分
list.forEach(System.out::println);
- A iteração externa é semelhante ao Iterador anterior. O ponteiro aponta para a coleção externamente e o método next () precisa ser chamado para mover o ponteiro para baixo, enquanto a iteração interna é equivalente a ser executada automaticamente dentro da coleção.
- Estatuto
@Test
public void test14(){
//T reduce(T identity, BinaryOperator<T> accumulator); 可以将流中元素反复结合起来,得到一个值,返回一个T
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
//Optional<T> reduce(BinaryOperator<T> accumulator); 可以将流中元素反复结合起来得到一个值,返回Optional<T>
//计算公司中所有员工工资的总和
List<Employee> list = EmployeeData.getEmployees();
Stream<Double> salaryStream = list.stream().map(Employee :: getSalary);
Optional<Employee> countMoney = salaryStream.reduce(Double :: sum);
//或者也可以自己写累加
Optional<Employee> countMoney = salaryStream.reduce((d1,d2) -> d1 + d2);
}
- recolher
@Test
public void test(){
//collect(Collector c) 将流转化为其他形式,接收一个Collector接口的实现,用于
List<Employee> list = EmployeeData.getEmployees();
//将工资中大于6000的放到一个list中
List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
employeeList.forEach(System.out::println);
//也可以放到一个set集合中,只需要调用Collectors中写好的静态方法就可以了
List<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
employeeSet.forEach(System.out::println);
}
- Método estático interno dos coletores