当前位置:   article > 正文

java8 函数式编程

java8 函数式编程

1.函数式编程思想

a>概念

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

2.lambda表达式(前提是参数接口,且接口中只有一个抽象方法

* 前提是参数接口,且接口中只有一个抽象方法 

  用lambda表示时 接口中的方法就会省略不写

a>概念

jdk1.8推出的,对某些匿名内部类写法进行简化,

他是函数编程思想的一个重要体现,不在关注是什么对象,更关注对数据进行什么操作。

b>语法格式

(参数列表)->{代码}

3.Stream流

java8Stream使用的是函数编程模式

可以用来对集合或数组进行链状流式操作

可以更方便的对集合和数组操作。

4.中间操作

  filter  distinct()  map  sorted  limit  skip flatmap

 map 只能将一个对象转换为另一个对象

flatmap 可以将一个对象转换为多个对象作为流中的元素

    list.stream()

                .distinct()     //去重复

                .sorted()   // //排序 实体类必须实现 compared接口,在重写方法中设置排序规则

                .sorted((item1,item2)->item1.getAge-item2.getAge)    //同上

                .limit(5)    //设置流的个数超出部分抛弃

                .skip(2)   //跳过前2条数据

                .flatmap(item->item.getBooks.stream()) //getBook是个集合 实际就是返回stream() 类型

                .filter(item->item>10 && item<20)  //过滤获取item大于10的数据  &&支持多条件过滤  

                .map(item->item.getName)   //转换类型,返回的类型与item.getName类型一致

                                                            (且数据流中只有这一列的值)      

                .sorted()

                .foreach(item->System.out.println(item)) ;

5.终结操作

  foreach  //遍历对元素进行操作

  count  //返回long型  即流中数据的个数

  collect  //把当前流转换为集合(list set map)

  max/min //返回最大值或最小值  只能是int类型  返回 Optional<Integer>

  anyMatch //是否有任意匹配的元素  返回boolean

  allMatch //是否全部符合条件 返回boolean

  noneMatch //是否都不符合条件 返回boolean

  findAny //获取流中任意一个元素 返回 Optional<Bean>

  findfirst //获取流中的第一个元素 返回 Optional<Bean>

  reduce //归并 对流中的元素按照给定的计算方式得到结果

list.stream()

                .foreach(item->System.out.println(item)) ;

                .count();

                .map(item->item.getAge) 

                .mix((age1,age2)->age1-age2) ;

                .map(item->item.getName) 

                .collect(Collectors.toList());  //将流中所有的name 转换为一个list

                .collect(Collectors.toSet());  //将流中所有的name 转换为一个set

                .distinct()  // map 的key不能重复,必须要去重复

                .collect(Collectors.toMap(item->item.getName(),item->item.getBooks()));  //将流中所有的name 转换为一个set

                .anyMatch(item->item.getAge>30);

                .allMatch(item->item.getAge>30);

                .noneMatch(item->item.getAge>30);

    Optional<Integer>  max = list.stream()  .

                                        .map(item->item.getAge) 

                                        .max((age1,age2)->age1-age2) ;

Optional<Bean>  any = list.stream()  .

                                        .filter(item->item.getAge>20) 

                                        .findAny () ;

any.ifPresent(item->System.out.print(item.getAge))

Optional<Bean>  first = list.stream()  .

                                        .filter(item->item.getAge>20) 

                                        .findFirst () ;

first .ifPresent(item->System.out.print(item.getAge))

6.Optional

    类似包装类,将对象封装进这个对象中,用来更好的处理空指针异常问题。

    用Optional的静态方法 ofNUllable(Bean) 封装,ifPresent()方法处理是否为空。

   ifPresent方法是:如果数据不为空,就执行输出

例: Optional<User> optional = Optional.onNullable(User);

         optional.ifPresent(user->System.out.println(user.getName));

优雅的处理控制住方式

参考文档:JAVA8之妙用Optional解决判断Null为空的问题_zjhred的博客-CSDN博客_java8 判断null

  1. //之前
  2. if(user!=null){ dosomething(user);}
  3. //现在
  4. Optional.ofNullable(user).ifPresent(u->{dosomething(u);});
  5. //之前
  6. public String getCity(User user) throws Exception{
  7. if(user!=null){
  8. if(user.getAddress()!=null){
  9. Address address = user.getAddress();
  10. if(address.getCity()!=null){
  11. return address.getCity();
  12. }
  13. }
  14. }
  15. throw new Excpetion("取值错误");
  16. }
  17. //现在
  18. public String getCity(User user) throws Exception{
  19. return Optional.ofNullable(user)
  20. .map(u-> u.getAddress())
  21. .map(a->a.getCity())
  22. .orElseThrow(()->new Exception("取指错误"));
  23. }
  24. //之前
  25. public User getUser(User user) throws Exception{
  26. if(user!=null){
  27. String name = user.getName();
  28. if("zhangsan".equals(name)){
  29. return user;
  30. }
  31. }else{
  32. user = new User();
  33. user.setName("zhangsan");
  34. return user;
  35. }
  36. }
  37. //现在
  38. public User getUser(User user) {
  39. return Optional.ofNullable(user)
  40. .filter(u->"zhangsan".equals(u.getName()))
  41. .orElseGet(()-> {
  42. User user1 = new User();
  43. user1.setName("zhangsan");
  44. return user1;
  45. });
  46. }

orElse 和 orElseGet 区别

    name.orElse("返回字符串")

    name.orElseGet(() -> "返回实现的对象")

7.并行流

 有俩种方式实现并行流;

 1>  stream().parallel()

 2>  parallelStream()

案例详解:

1.排序 sorted

a>按 BigDecimal 类型 nav 降序排序   存在空指针异常的情况

  1. // 降序排序 去掉reversed顺序反转
  2. List<Test> result = list
  3. .stream()
  4. .sorted(Comparator.comparing(Test::getNav).reversed())
  5. .collect(Collectors.toList());

b>. BigDecimal 类型 nav 降序排序,为空的数据 排最后

nullsFirst 为空时排第一  nullsLast 为空时排第最后   可以避免空指针

reversed顺序反转

  1. List<Test> result = list
  2. .stream()
  3. .sorted(Comparator.comparing
  4. (Test::getNav, Comparator.nullsFirst(BigDecimal::compareTo)).reversed())
  5. .collect(Collectors.toList());

 c>先按 : BigDecimal 类型 nav 升序排序,为空的数据 排最后

  再按:BigDecimal 类型 rate 升序排序,为空的数据 排最后

  1. List<Test> result = list.stream()
  2. .sorted(Comparator.comparing(Test::getNav,
  3. Comparator.nullsLast(BigDecimal::compareTo))
  4. .thenComparing(Test::getRate, Comparator.nullsLast(BigDecimal::compareTo)))
  5. .collect(Collectors.toList());

d>int 类型 年龄升序排序

  1. //将list按照年龄从小到大排序
  2. List<User> collect2 = list
  3. .stream()
  4. .sorted((s1, s2) -> s1.getAge() - s2.getAge())
  5. .collect(Collectors.toList());
  6. collect2.forEach(x->{
  7. System.out.print(x.getAge());
  8. });

e>LIst<Map<String,Object>> 按map中一个属性排序

  1. //age 为int类型,空的在最后排序
  2. List<Map<String, Object>> listMap = listMap
  3. .stream()
  4. .sorted(Comparator.comparing(a -> (Integer) a.get("age"),
  5. Comparator.nullsLast(Integer::compareTo)))
  6. .collect(Collectors.toList());

2.转换类型 map

a> list<BeanA>  转换为 list<BeanB>

  1. List<StockNoticesVO> result = stockNoticesPOList
  2. .parallelStream()
  3. .map(t -> {
  4. StockNoticesVO stockNoticesVO = new StockNoticesVO();
  5. BeanUtils.copyProperties(t, stockNoticesVO);
  6. return stockNoticesVO;
  7. })
  8. .collect(Collectors.toList());

b> list 转为 指定的 list或set

  1. //返回指定的集合 适合 list 和 set
  2. Set<String> resultSet= list
  3. .parallelStream()
  4. .map(t->t.getName)
  5. .collect(Collectors.toCollection(() -> Sets.newConcurrentHashSet()));

c> 将list<String > 中的小写元素转为大写

  1. List<String> results = list
  2. .stream()
  3. .map(String::toUpperCase)
  4. .collect(Collectors.toList());

d>list 转map,key为 age,value为name   key如果有重复的选第一个

  1. // 如果(k1, k2) -> k2key 重复时 选后面的一个
  2. list
  3. .stream()
  4. collect(Collectors.toMap(t-> t.getAge(), t::getName, (k1, k2) -> k1));

3.遍历元素操作  foreach

a>对原list<Bean> 属性重新赋值  修改是持久的

  1. list.stream()
  2. .forEach(t-> {
  3. String securityCode = "新securityCode ";
  4. String stockExchange = "新stockExchange "
  5. t.setSecurityCode(securityCode);
  6. t.setExchange(stockExchange);
  7. });

4> 过滤数据 filter

a> 获取 一个list<bean>中的属性 存在 与另一个list<Bean2> 中的属性相同的集合

  1. result = list
  2. .stream()
  3. .filter(t-> list2.stream()
  4. .anyMatch(t2->
  5. (t.getSecurityCode()).equals(t2.getSecurityCode())
  6. && (t.getExchange()).equals(t2.getExchange()
  7. )
  8. )
  9. )
  10. .collect(Collectors.toList());

b>多条件过滤

  1. //可以在filter 中写判断逻辑,必须返回boolean
  2. resultList = resultList .stream().filter(f -> {
  3. if (1!=1) {
  4. return false;
  5. }
  6. if (2 != 2) {
  7. return false;
  8. }
  9. return true;
  10. }).collect(Collectors.toList());

5.reduce

a>BigDecimal  求和

  1. //求和 并过滤掉空的情况
  2. BigDecimal sumData = e.stream().map(User::getMoney).filter(StringUtil::isNotEmpty).reduce((x, y) -> x.add(y)).orElse(BigDecimal.ZERO);

6.Collectors 中的方法

a>转map  key为tomap 中的第一个参数,value 为 第二个参数

  1. //返回map中的泛型为 Map<String, t> 对应 t.getName() T 的类型
  2. Map<String, t> resultMap = list<T>
  3. .stream()
  4. .collect(Collectors.toMap(t->t.getName(), t -> t));
  1. //返回指定的集合 适合 list 和 set
  2. Set<String> resultSet= list
  3. .parallelStream()
  4. .map(t->t.getName)
  5. .collect(Collectors.toCollection(() -> Sets.newConcurrentHashSet()));
  1. //返回key是id,value 为自定义的map
  2. Map<Integer, Map<String, Object>> resultMap= userList
  3. .stream()
  4. .collect(Collectors.toMap(User::getId, t -> {
  5. Map<String, Object> map = Maps.newHashMap();
  6. map.put("securityId", t.getSecurityId());
  7. map.put("securityName", t.getSecurityName());
  8. map.put("windCode",
  9. return map;
  10. }, (a, b) -> a)
  11. );

 参考文档:https://www.jb51.net/article/186960.htm#_lab2_2_6

a>maxBy   取出流总元素最大值       针对 int类型

  1. //取出集合中年龄的最大值
  2. Optional<User> collect1 = list
  3. .stream()
  4. .collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge()));

b>minBy 取出 流中元素中 长度最好的值   针对String类型

  1. Optional<String> min = list
  2. .stream
  3. .collect(Collectors.minBy(Comparator.comparingInt(String::length)));

c>joining  连接元素 针对String类型

  1. // 输出 FelordcnTomcatJettyUndertowResin
  2. list.stream().collect(Collectors.joining());
  3. // 输出 Felordcn,Tomcat,Jetty,Undertow,Resin
  4. list.stream().collect(Collectors.joining("," ));
  5. // 输出 [Felordcn,Tomcat,Jetty,Undertow,Resin]
  6. list.stream().collect(Collectors.joining(",", "[", "]"));

d>groupingBy  分组

参考文档:Stream中Collectors.groupingBy toMap mapping操作实例_一笑而过者也的博客-CSDN博客_collectors.mapping和map

  1. //分组 按某个属性分组 返回格式如下
  2. Map<String, List<Product>> prodMap= prodList
  3. .stream()
  4. .collect(Collectors.groupingBy(Product::getCategory));
  5. //{"啤酒":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},
  6. {"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],
  7. "零食":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},
  8. {"category":"零食","id":2,"name":"饼干","num":2,"price":20},
  9. {"category":"零食","id":3,"name":"月饼","num":3,"price":30}]}

e>Collectors.mapping  重写返回类型Collectors.mapping

参考文档:Java8 Stream Collectors groupingBy 和 mapping 配合使用 - 简书

  1. //分组后映射map为 sex-set(money)
  2. Map<String, Set<Double>> collect3 = students
  3. .stream()
  4. .collect(Collectors.groupingBy(Student::getSex,
  5. Collectors.mapping(Student::getMoney, Collectors.toSet())
  6. )
  7. );
  8. // 输出为 {女=[40.0, 80.0], 男=[10.0, 20.0]}

7.求平均值

a>Collectors.averagingInt   Collectors.averagingDouble

List<User>

Double averageAge= userList.stream().collect(Collectors.averagingInt(User::getAge));

List<Integer>

Double averageAge= userList.stream().collect(Collectors.averagingDouble(t->t);

b>mapToDouble

  1. OptionalDouble avg = listUsers.stream().mapToDouble(Users::getAge).average();
  2. if (avg .isPresent()) {  System.out.println(avg .getAsDouble()); }
  3. double avg = listUsers.stream().mapToDouble(Users::getAge).average().getAsDouble();

c>对BigDecimal类型取平均值

参考文档:java8计算list对象BigDecimal属性的最大值、最小值、总和、平均值_X_ABU的博客-CSDN博客_bigdecimal平均值

ROUND_HALF_UP 为四舍五入模式

BigDecimal average = userList.stream().map(User::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(userList.size()), 2, BigDecimal.ROUND_HALF_UP);

d>分组并求和 平均数等 

参考文档:​​​​​​利用stream对list集合中的bigdecimal进行分组求和,均值,最大值,最小值_泡^泡的博客-CSDN博客

  1. //按照性别求分数平均值
  2. Map<String, BigDecimal> scoreAvg = list.stream()
  3. .filter(t -> t.getScore() != null)
  4. .collect(Collectors.groupingBy(Student::getSex, CollectorsUtil.averagingBigDecimal(Student::getScore,2,0)));
  5.        
  6. System.out.println("----按照性别求分数平均值----");      
  7. scoreAvg.forEach((k,v) -> System.out.println("key: " + k + " , " + "value: " + v)); 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/289815
推荐阅读
相关标签
  

闽ICP备14008679号