Java jdk8版本特性(未完成版)
一、JDK8新特性
①引入Lambda表达式:
// 实现集合元素的遍历输出List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");// 老版本实现for(int i = 0 ; i < names.size() ; i++){system.out.println("姓名:" + names.get(i));
}for(String name : names){system.out.println("姓名:" + name);
}// JKD8 Lambda 实现names.foreach({value}->system.out.println("姓名: " + value));
②引入函数式接口
函数式接口在Java中指:有且只有一个抽象方法的接口(接口中可以包含其他方法如:默认方法、静态方法、私有方法)
函数式接口的核心设计目的:为了完美适配 Lambda 表达式(函数式接口有且只能有一个抽象方法,因此Lambda能够精准重写接口中的抽象方法)
@FunctionalInterface:
针对函数式接口 Java8 中引入了一种新注解----@FunctionalInterface 进行声明(编译器在编译时会对标注了该注解的接口进行判断,判断其是否只有一个抽象方法,如果多于一个或者少于一个则会报错)
函数式接口的使用:
// 定义一个函数式接口@FunctionalInterface
public interface MyFunctionalInterface(){//具有 有且只有一个 抽象方法public abstract void method();}// 假设该接口有一个实现类public class MyFunctionalInterfaceImpl implements MyFunctionalInterface{@Overridepublic void method(){System.out.println(“实现类的method方法”)}}// 在对应测试类中有以下使用方式:public class Demo {//定义一个方法,参数使用函数式接口 MyFunctionalInterfacepublic static void show(MyFunctionalInterface myInter){myInter.method();}public static void main(String[] args){//调用show方法,方法的参数是一个接口,所以可以传递该接口的实现类对象(多态)show(new MyFunctionalInterfaceImpl);//调用show方法,方法参数是一个接口,也可以直接传递该接口的匿名内部类show(new MyFunctionalInterface(){@Overridepublic void method(){System.out.println("使用匿名内部类重写的method");}};//调用show方法,方法参数是一个接口,也可以直接用lambda表达式实现show( () -> { System.out.println("使用Lambda表达式重写接口中的method方法"); } )}
③增加方法和构造函数的引用
方法引用/构造函数引用:允许通过方法名直接引用已有方法,替代Lambda表达式
方法引用:
-- 引用方法Convert<String, Integer> converter = Integer :: valueOf; //定义一个类型转换器 , 转换规则 -> Integer中的valueOf方法Integer converted = converter.convert("123");System.out.println(converted.getClass());
④提供了很多函数式接口
⑤引入了Streams流
Streams流:表示能应用在一组元素上一次执行的操作序列
Streams流操作分为中间操作+最终操作,最终操作返回特定类型的计算结果,中间操作返回Stream本身。
Streams流对集合常见操作:
收集(将流元素聚合到集合或者其他数据结构中):
方法:collect(Collector)
常用收集器:
Collectors.toList():收集为List集合
Collectors.toSet():收集为Set集合
Collectors.joining():拼接为字符串
Collectors.groupingBy():按条件分组
--- 返回值为Map<P,T>类型 P为你分组的条件数据 T为按条件分类后的对应数据
例子:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");//转化为Set集合
Set<String> nameSet = names.stream().collect(Collectors.toSet());//按字符串长度分组
Map<Integer,List<String>> groupByLength = names.stream().collect( Collectors.groupingBy(String::length));// 按字符串长度分组:{3=[Bob], 5=[Alice], 7=[Charlie]}
Filter(过滤):
通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作。
-- Predicate<T> 函数式接口定义@FunctionalInterface
public interface Predicate<T> {boolean test(T t); //输入一个元素,返回布尔值
}-- Stream接口的Filter方法定义Stream<T> filter(Predicate<? super T> predicate);
List<User> users = Arrays.asList(new User("Alice", 28, "北京"),new User("Bob", 22, "上海"),new User("Charlie", 25, "北京")
);// 过滤出年龄在25-30区间内的数据List<User> filteredUsers = users.stream().filter(u -> u.getAge()>=25 && u.getAge() <= 30).collect(Collectors.toList());// 过滤出地址为北京的数据List<User> filteredUsers = users.stream().filter(u -> u.getCity().equals("北京")).collect(Collectors.toList());// 过滤出姓名以B开头的用户List<User> filteredUsers = users.stream().filter(u -> u.getUserName().startwith("B")).collect(Collectors.toList());
Sorted(排序):
排序是一个中间操作,返回的是一个排序后的Stream,如果不指定一个自定义的 Comparator 则会使用默认排序。
-- Sort排序stringList.stream().sorted().filter(s->s.startWith("a")).forEach(System,out::println);
需要注意的是,排序只创建了一个排列好后的 Stream,而不会影响原有的数据源,排序之后原数据 stringList 是不会被修改的。
Map(映射):
将元素根据指定的Function接口来依次将元素转换成另外的对象,map也是一个中间操作。
-- 测试Map操作stringList.stream().map(String::toUpperCase) //将集合中所有数据转为大写.sorted((a,b) -> b.compareTo(a)) //反转集合顺序.forEach(System.out::println); //迭代输出元素
Match(匹配):
Stream提供了多种匹配操作,允许监测指定的Predicate(同上文过滤)是否匹配整个Stream。所有的匹配操作都是最终操作,并返回一个boolean类型的值。
-- 遍历流中的元素,对每个元素使用predicate.test(element)// anyMatch-- 如果存在至少一个元素使得方法返回true,则立即返回true并终止处理
-- 如果所有元素都不满足,返回falseboolean anyStartsWithA = stringList.stream().anyMatch(s->s.startWith("a"));// allMatch-- 如果所有元素都能使方法返回true,则返回true
-- 如果存在一个元素都不满足,返回falseboolean allStartsWithA =stringList.stream().allMatch((s) -> s.startsWith("a"));// noneMatch-- 如果存在元素使方法返回true,则返回false
-- 如果不存在元素能够返回true,返回trueboolean noneStartsWithZ = stringList.stream().noneMatch((s) -> s.startsWith("z"));
Count(计数):
返回Stream中的元素个数,返回值类型为long,是一个最终操作
-- Count 计数操作long startsWithB = stringList.stream().filter((s) -> s.startsWith("b")).count();