java 8 新特性(二) stream API

java 8 新特性(二) stream API

stram的三个操作 :

  1. 创建stram
  2. 中间操作
  3. 终止操作(终端操作)

一、创建stream的几种方式:

// 第一种: 可以通过Collection 系列集合提供的 stream() 或 parallelStream()
        Map<String,Object> map = new HashMap<>();
        employees.stream(); // 串行流
        employees.parallelStream(); // 并行流
        System.out.println("--------------------------------------------------------------");

        // 第二种. 通过 Arrays 中静态方法 stream() 获取数组流
        Integer[] array = new Integer[10];
        Stream<Integer> stream = Arrays.stream(array);

        System.out.println("--------------------------------------------------------------");

        // 第三种: 通过stream() 类中的静态方法 of()
        Stream<String> stream3 = Stream.of("aa","bb","cc");

        // 第四种: 创建无限流(无穷尽) 迭代
        /**
         *  iterate:
         *   该方法实现了 函数式接口
         *   @FunctionalInterface
         *   public interface UnaryOperator<T> extends Function<T, T> {}
         *
         *   三个步骤的体现:(基本上stream的操作都会存在该三步)
         *   Stream.iterate(9,x->x+2).limit(10).forEach(System.out::println);
         *   Stream.iterate(9,x->x+2) : 开始
         *   .limit(10): 中间操作
         *   .forEach(System.out::println): 终止操作
         */
//        Stream.iterate(9,x->x+2).forEach(System.out::println);

        Stream.iterate(9,x->x+2).limit(10).forEach(System.out::println);



结果:
--------------------------------------------------------------
--------------------------------------------------------------
9
11
13
15
17
19
21
23
25
27

二、stream 的中间操作的方法API:

测试数据:

 public static List<Employee> employees = Arrays.asList(
            new Employee("张三",18,1111.00),
            new Employee("李四",28,2222.00),
            new Employee("王五",38,3333.00),
            new Employee("赵六",48,4444.00),
            new Employee("候七",58,5555.00)
    );

(筛选与切片)

  • filter 在流中排除某些元素

  • distinct 筛选 通过 hashCode 与 equals 去重

  • limit 截断 使元素不超过给定的数量

System.out.println("--------------------------------------------------------------");
// 中间操作 filter  中间操作后面必须要有终止操作,若没有终止操作  中间操作的流没有任何结果的
employees.stream().filter(x -> x.getAge() >35).forEach(System.out::println);
System.out.println("--------------------------------------------------------------");
/**
 * 惰性求值:
 *      就是多个中间操作可以连接起来行成一个流水线,除非流水线上触发了终止操作,
 *      否则中间操作不会执行任务的处理,而在终止操作时一次性全部执行
 * 内部迭代: 迭代操作时有stream api完成
 * 外部迭代: 自己通过迭代语句执行
 */

结果: 
--------------------------------------------------------------
Employee{name='王五', age=38, salary=3333.0}
Employee{name='赵六', age=48, salary=4444.0}
Employee{name='候七', age=58, salary=5555.0}
--------------------------------------------------------------
  • skip 跳过元素 返回一个扔掉了钱n个元素的流 若流中元素不足n个, 则返回一个空流 与limit() 互补
// .skip(2) 跳过两条数据 取第三条数据
employees.stream().filter(x->x.getAge()>35).skip(2).forEach(System.out::println);    
结果: 
Employee{name='候七', age=58, salary=5555.0}

(映射)

  • map 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个元素
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
strings.stream().map(str->str.toUpperCase()).forEach(System.out::println);

结果:
AA
BB
CC
DD		

采用语法糖的方式:

// 类名::方法名  这是java的语法糖
strings.stream().map(StramAPI01::filterCharacter)
.forEach(x->x.forEach(System.out::println));

private static Stream<Character> filterCharacter(String str){
	List<Character> list = new ArrayList<>();
    for (Character ch: str.toCharArray()){
    	list.add(ch);
    }
    return list.stream();
}


结果:
a
a
b
b
c
c
d
d
  • mpaToDouble 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个DoubleStream

  • mapTOInt 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个intStream

  • mapToLong 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个longStream

  • flatMap 接收一个函数为参数 将流中的每个值都换成另一流 然后把所有的流连成一个流程

以上采用  采用语法糖的方式 的简化 采用 flatMap 可以实现

strings.stream().flatMap(StramAPI01::filterCharacter).forEach(System.out::println);

结果:
a
a
b
b
c
c
d
d

flatMap 与 map的区别

举例说明:

有二箱鸡蛋,每箱5个,现在要把鸡蛋加工成煎蛋,然后分给学生。

map做的事情:把二箱鸡蛋分别加工成煎蛋,还是放成原来的两箱,分给2组学生;

flatMap做的事情:把二箱鸡蛋分别加工成煎蛋,然后放到一起【10个煎蛋】,分给10个学生;

(排序)

  • sorted() 产生一个新流 其中按自然顺序排序

  • sorted(Comparator comp) 产生一个新流 其中按比较器顺序排序

List<String> strings = Arrays.asList("ee","aa", "bb", "cc", "dd");
strings.stream().sorted().forEach(System.out::println);

结果:
aa
bb
cc
dd
ee

-- 带参数的排序  按照年龄来排序
employees.stream().sorted((x1,x2)-> x1.getAge().compareTo(x2.getAge())).forEach(System.out::println);

结果:
Employee{name='张三', age=18, salary=1111.0}
Employee{name='李四', age=28, salary=2222.0}
Employee{name='李四1', age=29, salary=2233.0}
Employee{name='王五', age=38, salary=3333.0}
Employee{name='赵六', age=48, salary=4444.0}
Employee{name='候七', age=58, salary=5555.0}

三 、stream 的终止操作的方法API:

(查找与匹配)

  • allMath 检查是否匹配所有元素
boolean b1 = empLists.stream().allMatch(x->x.getAge().equals(18));
System.out.println("b1=="+ b1);

结果:
b1==false

  • anyMath 检查是否至少匹配一个元素
boolean b2 = empLists.stream().anyMath(x->x.getAge().equals(18));
System.out.println("b2=="+ b2);
结果:
b2==true

  • noneMath 检查是否有匹配的所有与元素
boolean b3 = empLists.stream().noneMath(x->x.getAge().equals(18));
System.out.println("noneMath b3=="+ b3);
结果:
noneMath b3==false

  • findFirst 返回第一个元素
Optional<Employee> em1 = empLists.stream().findFirst();
System.out.println("findFirst em1=="+ em1);

结果:
findFirst em1==Optional[Employee{name='张三', age=18, salary=1111.0}]

  • findAny 返回当前流中的任意元素
Optional<Employee> o1 = empLists.stream().findAny();
System.out.println("findAny 01=="+ o1);

结果:
findAny 01==Optional[Employee{name='张三', age=18, salary=1111.0}]

  • count
long count = empLists.stream().count();
System.out.println("count == "+ count);

结果:
count == 6

  • max min
Optional<Employee> max = empLists.stream()
					.max((x1,x2)->Integer.compare(x1.getAge(),x2.getAge()));
System.out.println("max==="+ max);
Optional<Employee> min = empLists.stream()
 							.min((x1,x2)->Integer.compare(x1.getAge(),x2.getAge()));
System.out.println("min==="+ min);


结果:
max===Optional[Employee{name='候七', age=58, salary=5555.0}]
min===Optional[Employee{name='张三', age=18, salary=1111.0}]

四、归约与收集 reduce 与 collect

  • reduce
System.out.println("--------------------------------------------------------------");

List<Integer> list = Arrays.asList(1, 2, 4, 5, 6, 7, 3, 56, 10);
Integer sum = list.stream().reduce(0,(x,y)->x+y);  // sum==94
System.out.println("sum=="+ sum);

System.out.println("--------------------------------------------------------------");
Integer sum1 = list.stream().reduce(1,(x,y)->x+y);  // sum==95
System.out.println("sum1=="+ sum1);

System.out.println("--------------------------------------------------------------");
// 计算员工的工资总和
Optional<Double> sum2 = employees.stream().map(Employee::getSalary)
						.reduce(Double::sum); // sum2===18898.0
System.out.println("sum2==="+ sum2.get());

备注:map 和 reduce 的连接通常称为 map-reduce 模式 ,因 Google 用它来进行网络搜索而出名

  • collect
// collect 收集器
// 案例1: 收集集合中的名字 
List<String> nameList1 = employees.stream()
    .map(Employee::getName)  // 取出Employee中的员工名字
    // Collectors : 计算集合的工具类
    .collect(Collectors.toList());
System.out.println("nameList1 == "+ nameList1); 
// nameList1 == [张三, 李四, 王五, 李四1, 赵六, 候七]


// 案例2:获取员工工资的平均值
Double d = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
 System.out.println("d ===="+ d); // d ====3149.6666666666665
 
 
 //案例3:  分组  将集合List<Map>转换成map<key,List<Map>>类型
 
Map<Employee.Status,List<Employee>> map =
         empLists.stream().collect(Collectors.groupingBy(Employee::getStatus));
System.out.println("map =="+ map);

// map =={
// VOCATION=[Employee{name='李四', age=28, salary=2222.0}, 
// Employee{name='候七', age=58, salary=5555.0}], 
// BUSY=[Employee{name='张三', age=18, salary=1111.0}, Employee{name='李四1', age=29, salary=2233.0}], 
// FREE=[Employee{name='王五', age=38, salary=3333.0}, Employee{name='赵六', age=48, salary=4444.0}]}


// Map<String,Map<String,List<Employee>> 类型
Map<Employee.Status, Map<String, List<Employee>>> map1 = empLists.stream()
    .collect((
        Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(
            e -> {
                if (((Employee) e).getAge() <= 35) {
                    return "青年";
                } else if (((Employee) e).getAge() <= 50) {
                    return "中年";
                } else {
                    return "老年";
                }
            }
        ))
    ));

// 结果: 
map1 == {VOCATION={青年=[Employee{name='李四', age=28, salary=2222.0}], 老年=[Employee{name='候七', age=58, salary=5555.0}]}, BUSY={青年=[Employee{name='张三', age=18, salary=1111.0}, Employee{name='李四1', age=29, salary=2233.0}]}, FREE={中年=[Employee{name='王五', age=38, salary=3333.0}, Employee{name='赵六', age=48, salary=4444.0}]}}


五、并行流 与 串行流

Optional

Optional 容器类的常用方法

  • Optional .of(T t) 创建一个一个Optional
  • Optional.empty() 创建一个空的Optional 实例
  • Optional.ofNullable(T t) 若t为null 创建Optional实例,否则创建空实例
  • Optional.isPresent() 判断是否包含值
  • Optional.orElse(T t) 如果调用对象包含值,返回该值,否则返回t
  • Optional.orElseGet(Supplier s) 如果调用对象包含值,返回改值,否则返回s 获取的值
  • Optional.,map(Function f) 如果值对其处理,并返回处理后的Optional 否则返回Optional.empty()
  • Optional.flatMap(Function mapper) 与map类似,要求返回值必须是Optional
posted @ 2021-01-10 20:45  小幸福_h  阅读(133)  评论(0编辑  收藏  举报