java8 主要新特性
一、lambda表达式
Runnable run = () ->{
System.out.println("hello");
};
格式:
- lambda操作符(箭头操作符): ->
- 操作符左边:lambda形参列表,即:接口中的抽象方法的形参列表
- 操作符右边:方法体,即:接口抽象方法的方法体
特殊情况:
- lambda表达式的参数列表的参数类型可以省略(类型推断);如果只有一个参数,小括号可以省略
- lambda体应用大括号包起来;如果只有一条语句,大括号可以胜率(此时,如果有返回值,return必须省略)
- 实现的接口必须时函数式接口(接口中只有一个抽象方法)
函数式接口:
1.消费型(Consumer):传入参数无返回值
public static void main(String[] args) {
ConsunerTest("this is ConsumerTest", new Consumer<String>() { //原始是实现
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("-----------lambda--------------");
ConsunerTest("this is lambda of ConsumerTest",s -> System.out.println(s));
}
public static void ConsunerTest(String s, Consumer<String> consumer){ //方法中使用Consumer函数式接口
consumer.accept(s); //函数式接口中抽象方法传入参数,无返回值
}
2.供给型(Supplier):无传入参数,有返回值
public static void main(String[] args) {
SupplierTest("this is ", new Supplier<String>() { //原始是实现
@Override
public String get() {
return "supplierTest";
}
});
System.out.println("----------------lambda---------------");
SupplierTest("this is lambda of", () -> "supplierTest");
}
public static void SupplierTest(String s, Supplier<String> supplier){ //方法中使用Supplier函数式借楼
String s1 = supplier.get(); //获取函数式接口的方法返回值
System.out.println(s + " " + s1);
}
3.函数型(Function):传入T,返回R
4.断言型(Predicate):传入T,返回Boolean
public static void main(String[] args) {
List list = new ArrayList();
list.add(123);
list.add(false);
list.add("this is PredicateTest");
list.add(56.23);
List<String> stringList1 = PredicateTest(list, new Predicate() { //原始是实现
@Override
public boolean test(Object o) {
if (o instanceof String) { //如果式字符串则返回true,否则返回false
return true;
} else {
return false;
}
}
});
System.out.println(stringList1);
System.out.println("---------------lambda---------------");
List<String> stringList2 = PredicateTest(list, s -> {
if (s instanceof String) {
return true;
} else {
return false;
}
});
System.out.println(stringList2);
}
//传入一个集合,将集合中的字符串过滤出来,并返回
public static List<String> PredicateTest(List list, Predicate predicate){
List<String> filter = new ArrayList<>();
for (Object s : list) {
if(predicate.test(s)){
filter.add((String)s);
}
}
return filter;
}
二、方法引用
本质上式lambda表达式
使用前提:抽象方法已有lambda实现,则可以使用方法引用代替lambda;·接口中的抽象方法的形参列表和返回值类型与方法引用中的形参列表和返回值类型一致
**格式:**类或对象 ::方法名
三种情况:
-
对象::非静态方法
System.out.println("----------lambda-------------"); Consumer<String> con = s -> System.out.println(s); //lambda中的方法实现打印 con.accept("this is test"); System.out.println("----------方法引用-------------"); PrintStream ps = System.out; Consumer<String> con2 = ps::println; //方法引用,前面为对象,后面为具体方法 con2.accept("this is test2");
-
类::静态方法
System.out.println("---------------lambda表达式---------------"); Comparator<Integer> com1 = (n1,n2)->Integer.compare(n1, n2); System.out.println(com1.compare(15, 65)); System.out.println("---------------方法引用--------------------"); Comparator<Integer> com2 = Integer::compare; //类::方法名 System.out.println(com2.compare(66, 55));
-
类::非静态方法
System.out.println("------------lambda--------------------"); Function<Class,String> fun1 = c -> c.getName(); //传入一个参数Class类型,返回字符串类型 System.out.println(fun1.apply("aaa".getClass())); System.out.println("------------方法引用--------------------"); Function<Class,String> fun2 = Class::getName; //传入的参数类型与lambda中的参数列表类型一致,参数作为调用方法者 System.out.println(fun2.apply("test".getClass()));
System.out.println("-----------------lambda-------------------------"); Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2); //传入两个String类型,返回int System.out.println(com1.compare("abc", "bcd")); System.out.println("-----------------方法引用-------------------------"); Comparator<String> com2 = String::compareTo; //第一个参数调用方法,传入第二个参数(两个参数类型与lambda中参数列表类型一致) System.out.println(com2.compare("abc", "bcd"));
三、构造器应用
persion类
public class Persion {
private int id;
private String name;
private char sex;
public Persion() {
}
public Persion(int id, String name) {
this.id = id;
this.name = name;
}
public Persion(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public String toString() {
return "persion{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
'}';
}
}
1.无参构造器引用
System.out.println("-----------lambda---------");
Supplier<Persion> s1 = () -> new Persion(); //Supplier函数式接口方法没有传入参数,有返回值;可使用无参构造器直接返回
System.out.println(s1.get());
System.out.println("-----------构造器引用---------");
Supplier<Persion> s2 = Persion::new; //构造器引用:返回类型::构造器(函数式接口中方法的传入参数列表对应构造器的参数列表)
System.out.println(s2.get());
2.一个参数构造器引用
System.out.println("-----------lambda---------");
Function<String,Persion> s1 = (s) ->new Persion(s); //Function函数式接口中方法有一个传入参数,一个返回值;可使用一个参数的构造方法
System.out.println(s1.apply("zhangsan"));
System.out.println("-----------构造器引用---------");
Function<String,Persion> s2 = Persion::new;
System.out.println(s2.apply("lisi"));
2.两个参数的构造器引用
System.out.println("-----------lambda---------");
BiFunction<Integer,String,Persion> s1 = (id,name) -> new Persion(id,name);
System.out.println(s1.apply(1, "zhangsan"));
System.out.println("-----------构造器引用---------");
BiFunction<Integer,String,Persion> s2 = Persion::new;
System.out.println(s2.apply(2, "lisi"));
四、Stream API
Stream关注的式对数据的运算
Stream的操作步骤:
- 创建Stream:(集合或数组)获取一个流
- 中间操作:一个中间操作,对数据源进行操作
- 终止操作:一旦执行终止操作,就执行中间操作链,并产生结果
创建Stream方式
@Test
public void test1(){
//通过集合
List<Persion> list = new ArrayList<>();
Stream<Persion> stream = list.stream(); //返回一个顺序流
Stream<Persion> persionStream = list.parallelStream(); //返回一个并行流
}
@Test
public void test2(){
//通过数组
int [] arr = {1,2,3,4,5,6,8};
IntStream stream = Arrays.stream(arr); //直接使用Arrays的stream()方法,返回流
}
@Test
public void test3(){
//通过Stream的of
Stream<Integer> integerStream = Stream.of(1, 2, 2, 3, 14);
}
@Test
public void test4(){
//创建无限流
//使用iterate;实现从0开始,遍历偶数
Stream.iterate(0,(t)->t+2).limit(5).forEach(System.out::println); //参数:起始值,操作;limit为中间操作;foreach为终止操作
//使用generate
Stream.generate(()->Math.random()).limit(5).forEach(System.out::println);
}
中间操作
筛选与切片
//筛选与切片
@Test
public void test1(){
List<Integer> list = Arrays.asList(54, 24, 68, 87, 35, 94, 27, 54, 27);
//1.filter过滤
list.stream().filter((num)-> num>=50).forEach(System.out::println); //使用filter(参数为predicate函数式接口);实现过滤数组中>=50de数
System.out.println("************************");
//2.limit截断
list.stream().limit(3).forEach(System.out::println); //通过limit截断,只显示前面的3个元素
System.out.println("************************");
//skip跳过,
list.stream().skip(3).forEach(System.out::println); //跳过前面的几个数据
System.out.println("************************");
//distinct筛选,根据hashcode和equals取出重复元素
list.stream().distinct().forEach(System.out::println);
}
映射
//映射:通过方法将stream中的每一个元素映射到其中完成实现
@Test
public void test2(){
//map
List<Integer> list1 = Arrays.asList(1,2,3,4,5);
list1.stream().map(num -> num+1).forEach(System.out::println);
System.out.println("********************");
//flatMap
}
排序
//排序
@Test
public void test1(){
List<Integer> list = Arrays.asList(2, 5, 4, 3, 9, 7);
List<Persion> list2 = Arrays.asList(new Persion(1, "a"), new Persion(4, "b"), new Persion(2, "c"), new Persion(3, "d"));
//sorted()自然排序
list.stream().sorted().forEach(System.out::println); //将list从小到大自然排序
list2.stream().sorted().forEach(System.out::println); //list2根据Persion类中实现Comparable接口的方法进行排序
System.out.println("*******************");
//sorted(comparator com)定制排序
list.stream().sorted((n1,n2) -> -(n1-n2)).forEach(System.out::println); //list根据自定义方法排序
list2.stream().sorted((p1,p2) ->-(p1.getId()-p2.getId())).forEach(System.out::println); //根据Comparator对象实现自定义排序
}
终止操作
匹配与查找
//allMatch检查是否匹配所有元素
List<Integer> list = Arrays.asList(7, 6, 2, 3, 4, 5, 7, 9);
boolean b = list.stream().allMatch(num -> num > 0); //检查是否所有元素都大于0
System.out.println(b); //true
//anyMatch检查是否匹配至少一个
boolean b1 = list.stream().anyMatch(num -> num >= 9);
System.out.println(b1); //true
//noneMatch检查是否没有匹配的
boolean b2 = list.stream().noneMatch(num -> num > 10);
System.out.println(b2); //true
//findFirst查找第一个元素
Optional<Integer> first = list.stream().findFirst();
System.out.println(first);
//findAny查找任意元素
Optional<Integer> any = list.parallelStream().findAny();
System.out.println(any);
//count查找元素个数
long count = list.stream().filter(num -> num>5).count(); //查找大于5的元素个数
System.out.println(count);
//max获得最大值
Optional<Integer> max = list.stream().max(Integer::compare); //Comparator接口的方法引用
System.out.println(max);
//min获得最小值
Optional<Integer> min = list.stream().min(Integer::compareTo);
System.out.println(min);
//foreach内部迭代
list.stream().forEach(System.out::println);
归约
//归约
//reduce(T identity, BinaryOperator)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//实现计算1-10的和;identity为初始值;BinaryOperator为传入两个参数,返回一个值的函数式接口;Integer中的sum方法也是传入两个数,返回二者之和
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
//reduce(BinaryOperator)
Optional<Integer> reduce1 = list.stream().reduce(Integer::sum);
System.out.println(reduce1);
收集
List<Integer> list = Arrays.asList(6, 5, 6, 1, 3, 7, 4, 9, 5, 2);
List<Integer> collect = list.stream().filter(num -> num > 5).collect(Collectors.toList()); //list
System.out.println(collect);
Set<Integer> collect1 = list.stream().filter(num -> num > 3).collect(Collectors.toSet()); //set
System.out.println(collect1);
五、Optional类
避免出现空指针
Optional.of(T t) optional.orElse(E e)
Optional.ofNullable(T t) optional.orElseGet(E e)
其他
Date Time API 改进
可重复注解
HashMap底层实现添加红黑树
接口添加默认方法和静态方法