jdk1.8新特性笔记:
特殊的接口
方法的调用
Lambda表达式
数据流编程
特殊的接口
JDK1.8之前的接口不可以有方法体,但从JDK1.8开始,接口中的方法可以带有方法体
为什么要添加这个特性?
接口就是为了定义一个标准,这个标准要求所有的实现类实现这些抽象方法。
但存在某些方法,所有的实现类代码都是一样的,索性就把这些代码挪到接口中。
使用的方法?
通过default来修饰这个方法
public interface IAnimal{
void run();
default void eat(){
System.out.println("吃");
}
}
实现类可以不必实现这个方法
public class Person implements IAnimal {
@Override
public void run() {
System.out.println("人跑");
}
}
测试
public class Test {
public static void main(String[] args) {
IAnimal a = new Person();
a.eat();
a.run();
}
}
方法的调用
若lambda体中的内容有方法已经实现了,那么可以使用“方法引用”
也可以理解为方法引用是lambda表达式的另外一种表现形式并且其语法比lambda表达式更加简单
- 方法引用的三种表现形式:
对象::实例方法名
类::静态方法名
类::实例方法名 (lambda参数列表中第一个参数是实例方法的调用 者,第二个参数是实例方法的参数时可用)
public void test() {
/**
*注意:
* 1.lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
* 2.若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
*
*/
Consumer<Integer> con = (x) -> System.out.println(x);
con.accept(100);
// 方法引用-对象::实例方法
Consumer<Integer> con2 = System.out::println;
con2.accept(200);
// 方法引用-类名::静态方法名
BiFunction<Integer, Integer, Integer> biFun = (x, y) -> Integer.compare(x, y);
BiFunction<Integer, Integer, Integer> biFun2 = Integer::compare;
Integer result = biFun2.apply(100, 200);
// 方法引用-类名::实例方法名
BiFunction<String, String, Boolean> fun1 = (str1, str2) -> str1.equals(str2);
BiFunction<String, String, Boolean> fun2 = String::equals;
Boolean result2 = fun2.apply("hello", "world");
System.out.println(result2);
}
构造器引用
格式:ClassName::new
public void test2() {
// 构造方法引用 类名::new
Supplier<Employee> sup = () -> new Employee();
System.out.println(sup.get());
Supplier<Employee> sup2 = Employee::new;
System.out.println(sup2.get());
// 构造方法引用 类名::new (带一个参数)
Function<Integer, Employee> fun = (x) -> new Employee(x);
Function<Integer, Employee> fun2 = Employee::new;
System.out.println(fun2.apply(100));
}
数组引用
格式:Type[]::new
public void test(){
// 数组引用
Function<Integer, String[]> fun = (x) -> new String[x];
Function<Integer, String[]> fun2 = String[]::new;
String[] strArray = fun2.apply(10);
Arrays.stream(strArray).forEach(System.out::println);
}
Stream
获取stream
// 1、数组 使用的Arrays类的stream方法
String[] arr = new String[]{"ab", "cd", "ef"};
Stream<String> arrStream = Arrays.stream(arr);
stream.forEach(s->System.out.println(s)); //使用完之后不能再使用,需要重新生成 才能再次使用
// 2、集合 直接使用集合获取流
List<String> list = Arrays.asList("ab", "cd", "ef");
Stream<String> colStream = list.stream();
// 3、值 直接使用静态方法,获取指定值的顺序排序流
Stream<String> stream = Stream.of("ab", "cd", "ef");
常用方法
forEach() 使用该方法迭代流中的每个数据
forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作。
sorted() 使用该方法排序数据
List<OptionHoldDTO>optionHoldDTOList = optionHoldDTOList.stream().filter(optionHoldDTO -> optionHoldDTO.getHoldType() != null)
.sorted(Comparator.comparingInt(OptionHoldDTO::getHoldType)).collect(Collectors.toList());
list.stream().sorted(Comparator.comparing(User::getAge)).forEach(user -> System.out.println(user));
多个元素排序:coreRspList = coreRspList.stream().sorted( Comparator.comparing(LoanOutStatisticsRspDto::getLoanOutAmount).reversed() .thenComparing(Comparator.comparing(LoanOutStatisticsRspDto::getToLoanOutAmount).reversed()) ).collect(Collectors.toList());
filter():使用该方法过滤
list.stream().filter((User user) -> user.getAge() > 50).forEach(user -> System.out.println(user));
limit():使用该方法截断
// 从第三个开始截断,只输出前三个
list.stream().limit(3).forEach(user -> System.out.println(user));
skip():与limit互斥,使用该方法跳过元素
// 跳过前三个元素,从第四个开始输出
list.stream().skip(3).forEach(user -> System.out.println(user));
Lambda表达式
lambda表达式本质上是一段匿名内部类,也可以是一段可以传递的代码
lambda最直观的优点:简洁代码
目标方法的参数是一个接口
接口中只有一个抽象方法,这个抽象方法不是Object里面的方法
接口最好顶一个注解:@FunctionalInterface
lambda如何写开发:
把接口中抽象的方法复制一份到代码中(一定要加注释)
接口中唯一的抽象方法`在这里插入代码
* public abstract void run();
* 最全的写法:它是唯一的抽象方法的简写
* (方法的形参) -> {方法体,如果有返回值,一定要写返回值}
* 最全的省略:
* 如果目标方法只有一个参数,可以省略小括号
* 小括号里面的形参:类型可以省略
* 如果方法体只有一行,大括号可以省略
常见的lambda表达式接口
所有的lambda表达式常见的工具类都在java.util.function
//匿名内部类
Comparator<Integer> cpt = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
TreeSet<Integer> set = new TreeSet<>(cpt);
System.out.println("=========================");
//使用lambda表达式
Comparator<Integer> cpt2 = (x,y) -> Integer.compare(x,y);
TreeSet<Integer> set2 = new TreeSet<>(cpt2);
Lmabda表达式的语法总结: () -> ();
前置 | 语法 |
---|---|
无参数无返回值 | () -> System.out.println(“Hello WOrld”) |
有一个参数无返回值 | (x) -> System.out.println(x) |
有且只有一个参数无返回值 | x -> System.out.println(x) |
有多个参数,有返回值,有多条lambda体语句 | (x,y) -> {System.out.println(“xxx”);return xxxx;} |
有多个参数,有返回值,只有一条lambda体语句 | (x,y) -> xxxx |
口诀:左右遇一省括号,左侧推断类型省
注:当一个接口中存在多个抽象方法时,如果使用lambda表达式,并不能智能匹配对应的抽象方法,因此引入了函数式接口的概念
数据流编程
分类
方法的返回值还是Stream:(Transformaction算子)
方法的返回值不是Stream:(action算子)
介绍
数据流编程的处理就像是像一根带阀门的管子里注水,每次处理就是一道阀门,水流就是数据,
只有一个数据处理完成之后,才会处理另一份数据
1.transformaction算子
package com.jinghangzz.jdk_new.stream;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.junit.Test;
/**
* 数据流编程
* @author TeaBig
*/
public class DataStream
{
/**
* 测试一个方法(框架)
*/
@Test
public void base()
{
/* 准备一个容器 */
List<Integer> intList = Arrays.asList(100,2,38,12,50,87);
/* 准备一个Stream */
Stream<Integer> souStream = null;
try
{
souStream = intList.stream();
/* 并行:多线程 */
//souStream = intList.parallelStream();
System.out.println("=isParallel==>" + souStream.isParallel());
/* 循环数据
* java.util.function.Consumer
* void accept(T t);
*
* forEach:action算子
* */
souStream.forEach( t -> System.out.println("==Stream循环==" + t));
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} finally
{
if(souStream != null)
{
souStream.close();
souStream = null ;
}
}
package com.jinghangzz.jdk_new.stream;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.junit.Test;
/**
* 数据流编程
* @author TeaBig
*/
public class DataStream
{
/**
* 测试一个方法(框架)
*/
@Test
public void base()
{
/* 准备一个容器 */
List<Integer> intList = Arrays.asList(100,2,38,12,50,87);
/* 准备一个Stream */
Stream<Integer> souStream = null;
try
{
souStream = intList.stream();
/* 并行:多线程 */
//souStream = intList.parallelStream();
System.out.println("=isParallel==>" + souStream.isParallel());
/* 循环数据
* java.util.function.Consumer
* void accept(T t);
*
* forEach:action算子
* */
souStream.forEach( t -> System.out.println("==Stream循环==" + t));
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} finally
{
if(souStream != null)
{
souStream.close();
souStream = null ;
}
}
}
/**
* 过滤
* 按照指定的条件,对数据流里面的数据进行过滤
*/
@Test
public void transformaction_Filter()
{
/* 准备一个容器 */
List<Integer> intList = Arrays.asList(100,2,38,12,50,87);
/* 准备一个Stream */
Stream<Integer> souStream = intList.stream() ;
/* 过滤
* java.util.function.Predicate<T>
* boolean test(T t);
*
* 只有一行代码,return可以省略
* */
Stream<Integer> filterStream = souStream.filter( (t) -> t > 50);
/* 循环数据
* java.util.function.Consumer
* void accept(T t);
*
* forEach:action算子
* */
filterStream.forEach( t -> System.out.println("==Stream循环==" + t));
/* 关闭 */
souStream.close();
}
/**
* 过滤
*/
@Test
public void transformaction_Filter_Base()
{
/* 准备一个容器 */
List<Integer> intList = Arrays.asList(100,2,38,12,50,87);
/* 准备一个Stream */
Stream<Integer> souStream = intList.stream() ;
/* 过滤算子 */
Stream<Integer> filterStream = souStream.filter( new Predicate<Integer>()
{
@Override
public boolean test(Integer t)
{
System.out.println("=filter==test=" + t);
return t > 50;
}
} );
filterStream.forEach( new Consumer<Integer>()
{
@Override
public void accept(Integer t)
{
System.out.println("==循环==" + t);
}
} );
/* 关闭 */
souStream.close();
}
/**
* map算子
* 按照指定的条件,对数据流里面的数据进行处理(加工)
*/
@Test
public void transformaction_Map()
{
/* 准备一个容器 */
List<Integer> intList = Arrays.asList(100,2,38,12,50,87);
/* 准备一个Stream */
Stream<Integer> souStream = null;
try
{
souStream = intList.stream();
/* map算子;要把输入参数,经过一个方法变成另外一个参数;(处理参数)
* java.util.function.Function<T, R>
* R apply(T t);
*
* 需求:要把这里面的整数,都加一个字符串
* */
Stream<String> mapStream = souStream.map( (t) -> t + "==我变化了");
/* 循环数据
* java.util.function.Consumer
* void accept(T t);
*
* forEach:action算子
* */
mapStream.forEach( t -> System.out.println("==Stream循环==" + t));
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} finally
{
if(souStream != null)
{
souStream.close();
souStream = null ;
}
}
}
/**
* FlatMap算子
* 它会对数据流里面的数据大小有要求
*/
@Test
public void transformaction_FlatMap()
{
/* 准备一个容器 */
List<String> strList = Arrays.asList("ab","cd","ef","test-hello-hadoop");
/* 准备一个Stream */
Stream<String> souStream = null;
try
{
souStream = strList.stream();
/* map算子;要把输入参数,经过一个方法变成另外一个参数;(处理参数)
* java.util.function.Function<T, R>
* R apply(T t);
*
* 需求:要把这里面的整数,都加一个字符串
*
* map的参数: Function<? super T, ? extends R> mapper;R木有要求
* flatMap的参数:Function<? super T, ? extends Stream<? extends R>> mapper;R要求必须是Stream;
* */
Stream<String> flatMapStream = souStream.flatMap( t ->
{
/* 把字符串根据-拆分开 */
String[] splitList = t.split("-");
/* 返回值还是Stream这里面放的是字符串 */
List<String> tempList = Arrays.asList(splitList);
return tempList.stream() ;
});
/* 循环数据
* java.util.function.Consumer
* void accept(T t);
*
* forEach:action算子
* */
flatMapStream.forEach( t -> System.out.println("==Stream循环==" + t));
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if(souStream != null)
{
souStream.close();
souStream = null ;
}
}
}
/**
* FlatMap算子
* 它会对数据流里面的数据大小有要求
*/
@Test
public void transformaction_other()
{
/* 准备一个容器 */
List<Integer> intList = Arrays.asList(100,2,50,50,50,87);
/* 准备一个Stream */
Stream<Integer> souStream = null;
try
{
souStream = intList.stream();
/*
* distinct:去重
* */
//Stream<Integer> stream = souStream.distinct();
/* 取前几条记录 */
//Stream<Integer> stream = souStream.limit(2);
/* 跳过前n条数据 */
//Stream<Integer> stream = souStream.skip(2);
/* 排序:默认升序 */
//Stream<Integer> stream = souStream.sorted();
/* java.util.Comparator<T>:
* int compare(T o1, T o2);
* */
//Stream<Integer> stream = souStream.sorted( (t1,t2) -> -(t1 - t2) );
Stream<Integer> stream = souStream.unordered();
/* 循环数据
* java.util.function.Consumer
* void accept(T t);
*
* forEach:action算子
* */
stream.forEach( t -> System.out.println("==Stream循环==" + t));
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if(souStream != null)
{
souStream.close();
souStream = null ;
}
}
}
}
2.action算子
reduce图
package com.jinghangzz.jdk_new.stream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.junit.Test;
/**
* 全是对一些action算子的测试
* @author TeaBig
*
*/
public class DataStreamAction
{
/**
* 数据流测试的基本代码
*/
@Test
public void base()
{
/* 准备一个List */
List<Integer> intList = Arrays.asList(100,2,38,12,50,87);
/* 准备一个Stream */
Stream<Integer> stream = intList.stream() ;
try
{
/* 循环 */
stream.forEach( t -> System.out.println("==循环==" + t));
}catch(Exception e)
{
if(stream != null)
{
/* 关闭 */
stream.close();
stream = null ;
}
}
}
/**
* 数据流测试的基本代码
* 数据流,只能碰到一个action算子
*/
@Test
public void other()
{
/* 准备一个List */
List<Integer> intList = Arrays.asList(1,2,3,4,5);
/* 准备一个Stream */
Stream<Integer> stream = intList.stream() ;
try
{
/* 把流里面的数据变成数组 */
// Object[] arrays = stream.toArray();
// System.out.println("==toString==>" + Arrays.toString(arrays));
/* 数据的数量 */
// long count = stream.count() ;
// System.out.println("==count==>" + count);
/* 查询每一个元素 */
// Optional<Integer> findFirst = stream.findFirst();
// System.out.println("==findFirst==>" + findFirst.get());
/* 获取到迭代器 */
// for (Iterator<Integer> iterator = stream.iterator(); iterator.hasNext();)
// {
// Integer intValue = (Integer) iterator.next();
// System.out.println("==循环==" + intValue);
// }
/* 获取最大值
* 先排序:(不管是升序还是降序,他始终认的是第一个)
* */
// Optional<Integer> maxOption = stream.max( (t1,t2) -> t1 - t2);
// System.out.println("==max=>" + maxOption.get());
/* 获取最小值 */
// Optional<Integer> minOption = stream.min( (t1,t2) -> t2 - t1);
// System.out.println("==min=>" + minOption.get());
/* 缩减
* 参数是:java.util.function.BinaryOperator<T>;得找有抽象方法的接口:
* java.util.function.BiFunction<T, U, R>
* 抽象方法是:R apply(T t, U u);
* 泛型T,U是输入参数,R是输出参数
* */
Optional<Integer> reduce = stream.reduce( (t1,t2) -> t1 + t2);
System.out.println("==reduce=>" + reduce.get());
}catch(Exception e)
{
if(stream != null)
{
/* 关闭 */
stream.close();
stream = null ;
}
}
}
}
总结
关联源码