首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >JDK8新特性

JDK8新特性

作者头像
爱撒谎的男孩
发布2019-12-31 16:20:27
发布2019-12-31 16:20:27
9180
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

文章目录

1. JDk8新特性

1.1. 函数式编程

1.1.1. 集合的foreach

1.1.2. lambda表达式轻松创建接口实例

1.1.3. 接口的默认方法和静态方法

1.1.4. Stream

1.1.4.1. filter

1.1.4.2. sorted

1.1.4.3. 查找和匹配

1.1.4.4. 归约

1.1.4.4.1. map

1.1.4.4.2. reduce

1.1.4.5. 分组

1.2. Optional

1.3. Collectors

1.3.1. toMap

1.3.2. toList

1.3.3. toSet

1.3.4. groupingBy

JDk8新特性

函数式编程

集合的foreach

  • List
    • 这里的表示List中每一个元素,可以不指定类型,JDK会自动推测出类型,但是也是可以使用()加上类型
    • 如果有一条语句可以直接在后面输出,如果有多行,那么可以在后面使用{}指定
代码语言:javascript
复制
Arrays.asList(1,2,4,1,76).forEach(e-> System.out.println(e));  
  Arrays.asList(1,2,4,1,76).forEach((Integer e)-> System.out.println(e)); 
  • Set
代码语言:javascript
复制
Set<Object> set=new HashSet<>(Arrays.asList(1,2,4,1,76));
   set.forEach(e-> System.out.println(e));
  • Map
代码语言:javascript
复制
Map<Object,Object> map=new HashMap<>();
      map.put("2",2);
      map.put("4",5);
      //a,b两个元素分别是key和value
      map.forEach((a,b)->{
          System.out.println(a+"---"+b);
      });

lambda表达式轻松创建接口实例

  • 条件:该接口只能有一个需要实现的方法(默认方法除外)
    • ()->{}:无参数的实现
    • item->{}:单个参数的实现,jdk能够默认推断出参数的类型
    • (String item1,String item2):指定参数的类型
  • FunctionalInterface:标记这个接口只能定义一个方法(除了默认的方法)
代码语言:javascript
复制
@FunctionalInterface
public interface UserService {
    String display(String name);
}
@Test
   public void test1(){
       UserService userService=name -> {
           return name;
       };
       userService.display("che");
   }

接口的默认方法和静态方法

  • 默认方法不需要实现,但是可以被覆盖
代码语言:javascript
复制
public interface Demo1 {
	
	/**
	 * 接口的静态方法
	 */
	static void display() {
		System.out.println("cdc");
	}
	
	/**
	 * 默认方法可以不实现,但是可以被覆盖
	 */
	default void play() {
		System.out.println("cdddd");
	}
}

Stream

  • Stream接口中包含许多对流操作的方法,这些方法分别为:
    • filter():对流的元素过滤
    • map():将流的元素映射成另一个类型
    • distinct():去除流中重复的元素
    • sorted():对流的元素排序
    • forEach():对流中的每个元素执行某个操作
    • peek():与forEach()方法效果类似,不同的是,该方法会返回一个新的流,而forEach()无返回
    • limit():截取流中前面几个元素
    • skip():跳过流中前面几个元素
    • toArray():将流转换为数组
    • reduce():对流中的元素归约操作,将每个元素合起来形成一个新的值
    • collect():对流的汇总操作,比如输出成List集合
    • anyMatch():匹配流中的元素,类似的操作还有allMatch()和noneMatch()方法
    • findFirst():查找第一个元素,类似的还有findAny()方法
    • max():求最大值
    • min():求最小值
    • count():求总数
filter
  • 过滤集合,实际是实现其中的test方法,返回的是一个Boolean类型的值,我们可以使用lambda表达式可以很轻松的实现集合的过滤
代码语言:javascript
复制
@Test	
   public void test2(){
       User user1 = new User();
       user1.setName("chen");
       user1.setAge(22);
       User user3 = new User();
       user3.setName("zheng");
       user3.setAge(22);
       User user2 = new User();
       user2.setName("zhou");
       user2.setAge(30);
       List<User> users=new ArrayList<>();
       users.add(user1);
       users.add(user2);
       users.add(user3);
/* 下面的语句类似如下
        *   users.stream().filter(item->item.getAge()>25).collect(Collectors.toList());
        */	
       List<User> collect = users.stream().filter(user -> {
           if (user.getAge() > 25) {
               return true;
           } else {
               return false;
           }
       }).collect(Collectors.toList());
   }
sorted
  • 有两个实现的方法,如下:
代码语言:javascript
复制
Stream<T> sorted(Comparator<? super T> comparator);
Stream<T> sorted();
代码语言:javascript
复制
例子如下:
Stream.of(1, 8, 5, 2, 1, 0, 9, 2, 0, 4, 8)
    .filter(n -> n > 2)     // 对元素过滤,保留大于2的元素
    .distinct()             // 去重,类似于SQL语句中的DISTINCT
    .skip(1)                // 跳过前面1个元素
    .limit(2)               // 返回开头2个元素,类似于SQL语句中的SELECT TOP
    .sorted()               // 对结果排序
    .forEach(System.out::println);
代码语言:javascript
复制
//按照age排序,实际上就是实现Comparator的接口方法compareTo
      users.sort((item1,item2)->{
          return item1.getAge()-item2.getAge();
      });
查找和匹配
  • Stream中提供的查找方法有anyMatch()、allMatch()、noneMatch()、findFirst()、findAny(),这些方法被用来查找或匹配某些元素是否符合给定的条件:
代码语言:javascript
复制
// 检查流中的任意元素是否包含字符串"Java"
boolean hasMatch = Stream.of("Java", "C#", "PHP", "C++", "Python")
        .anyMatch(s -> s.equals("Java"));
// 检查流中的所有元素是否都包含字符串"#"
boolean hasAllMatch = Stream.of("Java", "C#", "PHP", "C++", "Python")
        .allMatch(s -> s.contains("#"));
// 检查流中的任意元素是否没有以"C"开头的字符串
boolean hasNoneMatch = Stream.of("Java", "C#", "PHP", "C++", "Python")
        .noneMatch(s -> s.startsWith("C"));
// 查找元素
Optional<String> element = Stream.of("Java", "C#", "PHP", "C++", "Python")
        .filter(s -> s.contains("C"))
        // .findFirst()     // 查找第一个元素
        .findAny();         // 查找任意元素
归约
map
  • map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
代码语言:javascript
复制
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
  • map使用lambda表达式返回的类型就是最后的类型,下面我们将用户的年龄设置成两倍
代码语言:javascript
复制
@Test
   public void test2(){
       User user1 = new User();
       user1.setName("chen");
       user1.setAge(22);
       User user3 = new User();
       user3.setName("zheng");
       user3.setAge(22);
       User user2 = new User();
       user2.setName("zhou");
       user2.setAge(40);
       List<User> users=new ArrayList<>();
       users.add(user1);
       users.add(user2);
       users.add(user3);
       List<User> list = users.stream().map(item -> {
           item.setAge(item.getAge() * 2);
           return item;
       }).collect(Collectors.toList());
   }
reduce
  • 将两个元素进行归约操作,比如两个元素相加,但是这个操作的返回值一定要和操作之前的类型相同//归约操作,返回的是一个Optional类型的
代码语言:javascript
复制
//归约操作,返回的是一个Optional类型的
        Optional<Integer> optional = users.stream().map(item -> item.getAge()).reduce((item1, item2) -> item1 + item2);
        if (optional.isPresent()){
            System.out.println(optional.get());
        }
分组
  • 和关系数据库一样,流也提供了类似于数据库中GROUP BY分组的特性,由Collectors.groupingBy()方法提供:
代码语言:javascript
复制
/根据age进行分组,返回的是Map集合,key就是分组后的age,value是user对象
        Map<Integer, List<User>> listMap = users.parallelStream().collect(Collectors.groupingBy(item -> item.getAge()));
        listMap.forEach((key,value)->{
            System.out.println(key+"--->"+value);
        });
  • 但实际情况可能比这复杂,比如将价格在0-50之间的书籍分成一组,50-100之间的分成一组,超过100的分成一组,这时候,我们可以直接使用Lambda表达式来表示这个分组逻辑:
代码语言:javascript
复制
//根据age进行分组,返回的是Map集合,key就是分组后的age,value是user对象
        Map<String, List<User>> listMap = users.parallelStream().collect(Collectors.groupingBy(item -> {
            if (item.getAge() > 20) {
                return "A";
            } else {
                return "B";
            }
        }));
        listMap.forEach((key,value)->{
            System.out.println(key+"--->"+value);
        });

Optional

  • 文档
  • https://zhuanlan.zhihu.com/p/40966718
  • 创建方法:
    • public static <T> Optional<T> of(T value):value的值不能为null
    • public static <T> Optional<T> ofNullable(T value):value允许为空
  • 常用方法
    • public Optional<T> filter(Predicate<? super T> predicate):过滤其中的元素,如果返回true,那么保留,返回false去除该元素
    • public T orElse(T other):如果该元素的值为null,那么指定该值为other
代码语言:javascript
复制
User user = new User(22, "chenjiabing");
User user2 = Optional.ofNullable(user).filter(item->{
	return item.getAge()>30;
}).orElse(null);
代码语言:javascript
复制
Optional.ofNullable(user).filter(item->{
	return item.getAge()>30;
}).orElseGet(()->{
	System.out.println("该值为空");
	return new User(44, "zhengjiahe");
});
代码语言:javascript
复制
Optional<Integer> map = Optional.ofNullable(null).map(item->{
	System.out.println(item);
	//返回值也决定着你的类型
	return Integer.MAX_VALUE;
});

Collectors

  • 针对集合操作的封装类,结合Stream编程客可以很简单的实现

toMap

  • List直接转换为Map,使用JDK1.8的Stream编程
  • Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper):简单的将集合转换成Map,出现key重复的将直接抛出异常
    • keyMapper:指定的
    • valueMapper:指定的value
代码语言:javascript
复制
   Map<Integer, String> map = users.stream().collect(Collectors.toMap(User::getAge, User::getName));
`
  • public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction):用于解决key冲突的情况
    • mergeFunction:用于当出现key冲突的情况下解决方法,其中只需要实现apply方法即可,两个参数分别是重复的map的value值,返回值是指定的值
代码语言:javascript
复制
Map<Integer, String> map = users.stream().collect(Collectors.toMap(User::getAge, User::getName,(v1,v2)->v1+","+v2));
toList
  • 将结果转换成一个List集合
代码语言:javascript
复制
List<Integer> list = Stream.of(1, 2, 3, 4).collect(Collectors.toList()); 

toSet

  • 将结果转换成一个Set集合Set
代码语言:javascript
复制
<Integer> set = Stream.of(1, 2, 3, 4).collect(Collectors.toSet()); 

groupingBy

  • 将所得的结果根据指定的内容进行分组,所得结果是一个Map类型的数据
  • public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
    • 指定的key,value的默认类型为
代码语言:javascript
复制
Map<Integer, List<Integer>> map = Stream.of(1, 1, 3, 10, 2, 3, 4).collect(
           Collectors.groupingBy(Integer::intValue));

代码语言:javascript
复制
`public static 
  Collector> groupingBy(Function<? super T, ? extends K> classifier,
 Collector<? super T, A, D> downstream)`
代码语言:javascript
复制
Map<Integer, Set<Integer>> map = Stream.of(1, 1, 3, 10, 2, 3, 4).collect(
           Collectors.groupingBy(Integer::intValue, Collectors.toSet()));
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-06-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JDk8新特性
    • 函数式编程
      • 集合的foreach
      • lambda表达式轻松创建接口实例
      • 接口的默认方法和静态方法
      • Stream
    • Optional
    • Collectors
      • toMap
      • toSet
      • groupingBy
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档