目录
Lambda表达式
public void fun1() {
String spt=","; //lambda表达式会将变量转换为final类型
// final String spt = ",";
//(String e)显示声明参数 e 的类型 可忽略
Arrays.asList("a", "b", "c").forEach((String e) -> {
System.out.print(e + spt);
});
}
@functionalInterface 函数式接口声明
- 1,如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
- 2,如果我们在一个接口上声明了@FunctionalInterface注解,那么编译器就会
按照函数式接口的定义来要求该接口
- 3,如果接口只有一个抽象方法,但我们没有声明@FunctionInterface注解,那么
编译器依旧会将该接口看做成函数式接口
- 4 接口中的抽象方法间接或直接重写Object类中的方法,该接口中的抽象方法个数不会增加
@FunctionalInterface
public interface MyInterface {
void test();
/*抽象方法重写object类中的方法 不会使得该接口的抽象方法个数加1*/
/*所以@FunctionalInterface不会报错,符合函数式接口的定义*/
String toString();
boolean equals(Object o);
}
函数式接口的例子
- 接口采用上面第四点的接口
public class FunctionalInterfaceDemo {
public void test1(MyInterface myInterface) {
myInterface.test();
System.out.println("----------------------");
}
public static void main(String[] args) {
FunctionalInterfaceDemo functionalInterfaceDemo = new FunctionalInterfaceDemo();
/*采用匿名内部类的方式 实现接口*/
functionalInterfaceDemo.test1(new MyInterface() {
@Override
public void test() {
System.out.println("实现类");
}
});
/*采用lambda表达式的方法 实现接口*/
/*抽象方法没有参数 这必须 使用() */
functionalInterfaceDemo.test1( () -> {
System.out.println("lambda实现类");
});
}
}
函数式接口 比如 : Consumer类,Runnable类
Function函数式接口的使用
public class FunctionTest {
/*行为的描述*/
public int compute(int a, Function<Integer, Integer> function) {
/*function函数式接口的一个抽象方法,给定一个值,返回一个值*/
return function.apply(a);
}
public String resultString(Integer s, Function<Integer, String> function) {
return function.apply(s);
}
/*传统的写法 先定义行为*/
public int add(int a) {
return a + a;
}
/* 调用function接口的 compose方法*/
public int computeBefore(int a, Function<Integer, Integer> function1,
Function<Integer, Integer> function2) {
/*先运行function2.apply(a),把结果当参数再放入到function1.apply(a)中*/
return function1.compose(function2).apply(a);
}
/* 调用function接口的 andThen方法*/
public int computeAfter(int a, Function<Integer, Integer> function1,
Function<Integer, Integer> function2) {
/*先运行function1.apply(a),把结果当参数再放入到function2.apply(a)中*/
return function1.andThen(function2).apply(a);
}
public static void main(String[] args) {
FunctionTest functionTest = new FunctionTest();
/*lambda表达式 传递行为*/
System.out.println(functionTest.compute(2, data -> data * data));
System.out.println(functionTest.resultString(8, value -> String.valueOf(value + "toString")));
/*行为已经定义死了 只是一个面向对象的过程 , 而函数式编程 是 传递行为*/
System.out.println(functionTest.add(5));
/*也可以事先定义好行为*/
Function<Integer, String> action = data -> data.toString();
System.out.println(functionTest.resultString(10, action));
/*定义compose andThen 的行为*/
System.out.println(functionTest.computeBefore(10, e -> e * e, e -> e + e));
System.out.println(functionTest.computeAfter(10, e -> e * e, e -> e + e));
}
}
BiFunction 函数式接口的使用
public class BiFunctionTest {
public Integer compute(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {
return biFunction.apply(a, b);
}
public Integer compute(int a, int b, BiFunction<Integer, Integer, Integer> biFunction1,
Function<Integer, Integer> Function2) {
return biFunction1.andThen(Function2).apply(a, b);
}
public static void main(String[] args) {
BiFunctionTest biFunctionTest = new BiFunctionTest();
System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 + e2));
System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 / e2));
System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 * e2));
System.out.println(biFunctionTest.compute(5, 5, (e1, e2) -> e1 + e2, e3 -> e3 * e3));
}
}
predicate 函数式接口
public class PredicateTest {
/***
* 给定一个参数 判断条件 满足就返回true 否则 false
* @see Predicate#test(java.lang.Object)
*/
public static void main(String[] args) {
Predicate<String> predicate = e -> e.length()>5;
System.out.println(predicate.test("Memory"));
}
}
and方法 or方法 negate方法
/*predicate接口 其他方法的用法*/
public void conditionFilter(List<Integer> list,Predicate<Integer> predicate1,Predicate<Integer> predicate2){
for (Integer integer : list) {
/* and 方法 两个都要满足*/
/*or 方法 满足其中一个即可*/
/*negate 方法 取相反*/
if (predicate1.and(predicate2).test(integer)){
/* predicate1.or(predicate2).test(integer)*/
/*predicate1.and(predicate2).test(integer)*/
/*predicate1.and(predicate2).negate().test(integer)*/
System.out.println(integer);
}
}
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
PredicateTest predicateTest = new PredicateTest();
/*给定函数具体行为*/
predicateTest.conditionFilter(list,e ->e % 2 == 0);
System.out.println("- - - - - - - - - - - -");
predicateTest.conditionFilter(list,e -> e % 2 != 0);
System.out.println("- - - - - - - - - - - - ");
predicateTest.conditionFilter(list,e2 -> e2<8,e1 -> e1 % 2 ==0);
}
Supplier 函数式接口 get()方法的使用
- 没有参数 返回一个结果,使用场景可以是创建各种工厂等等
public class SupplierTest {
/*Supplier函数接口中 get()方法的使用*/
public void get(Supplier<String> supplier){
System.out.println(supplier.get());
}
public static void main(String[] args) {
SupplierTest supplierTest = new SupplierTest();
Supplier supplier = () -> "hello world";
supplierTest.get(supplier);
System.out.println("-------------------");
/*使用场景一 返回一个对象*/
Supplier<Person> supplier1 = () -> new Person();
System.out.println(supplier1.get().getClass());
/*使用构造方法调用 返回一个对象*/
Supplier<Person> supplier2 = Person::new;
System.out.println(supplier2.get().getClass());
}
}
BinaryOperator 函数式接口
- 该接口是bifunction的子类,是一个特殊的bifunction,bifunction是给定两个参数返回一个结果,这三个变量都是可以类型不一样的。但binaryOperator三个变量的类型都必须是一致的
public class BinaryOperatorTest {
/*binaryOperator()方法的使用*/
public Integer counter(Integer i , Integer b , BinaryOperator<Integer> binaryOperator){
return binaryOperator.apply(i,b);
}
/*BinaryOperator静态方法的使用*/
public String getMinString (String s2,String s1,Comparator<String> comparator){
return BinaryOperator.minBy(comparator).apply(s1,s2);
}
public String getMaxString (String s2,String s1,Comparator<String> comparator){
return BinaryOperator.maxBy(comparator).apply(s1,s2);
}
public static void main(String[] args) {
BinaryOperatorTest binaryOperatorTest = new BinaryOperatorTest();
Integer counter = binaryOperatorTest.counter(10, 15, (e1, e2) -> e1 * e2);
System.out.println(counter);
System.out.println("-----------------------------------");
System.out.println(binaryOperatorTest.getMinString("hhh","aaaa",(e1,e2) ->e1.length()-e2.length()));
System.out.println(binaryOperatorTest.getMaxString("aaahhhaaaaa","aaaa",(e1,e2) ->e1.length()-e2.length()));
}
}
Optional 类 详解
/**
*author huangh
*date 2018/10/14 16:02
*description Optional 是为了规避 常见的 空指针异常
*/
public class OptionalTest {
public static void main(String[] args) {
/*Optional 类 中的构造方法是私有的 因此不能 直接new
有三个构造对象 静态方法
of(value) 带参数
empty() 构造一个空的
ofNullable() 可以为空 也可以不为空
*/
Optional<String> optional = Optional.of("hello");
/*判断不为空才会执行下面的语句,替代 if(not null)*/
optional.ifPresent( e -> {
//do something
System.out.println(e);
});
/*如果optional容器里面的value为null的话就执行这条语句*/
System.out.println(optional.orElse("world"));
}
}
- 模仿使用场景(进阶):
先定义 一对多 animal类 和 tom类
public class OptionalTest2 {
public static void main(String[] args) {
Tom tom = new Tom();
tom.setName("bob");
Tom tom1 = new Tom();
tom1.setName("lily");
List<Tom> toms = Arrays.asList(tom, tom1);
Animal animal = new Animal();
animal.setTomList(toms);
Optional<Animal> optional = Optional.ofNullable(animal);
System.out.println(
/*如果容器中的value不为空就会执行 e ->e.getTomList() 否者 就是执行 orElse*/
optional.map( e -> e.getTomList()).orElse(Collections.emptyList())
);
}
}
方法引用
-
引用静态方法 ContainingClass::staticMethodName
-
引用某个对象的实例方法 containingObject::instanceMethodName
-
引用某个类型的任意对象的实例方法 ContainingType::methodName
-
引用构造方法 ClassName::new
public class MethodReferenceTest {
@Test
public void printlnTest() {
List<Integer> list = Arrays.asList(1, 2, 3, 5);
/*lambda表达式*/
list.forEach((e) -> System.out.println(e));
/*方法引用*/
list.forEach(System.out::println);
}
@Test
/* 方法引用: 静态引用*/
public void StaticClassReference() {
Student student1 = new Student("zhangsan", 15);
Student student2 = new Student("lishi", 52);
Student student3 = new Student("zhaoliu", 99);
List<Student> students = Arrays.asList(student1, student2, student3);
// students.sort((e1,e2) ->Student.compareStudentByScore(e1,e2));
// students.forEach(e -> System.out.println(e.getScore()));
students.sort(Student::compareStudentByScore); // 静态方法引用
students.forEach(e -> System.out.println(e.getScore()));
}
@Test
/*方法引用代替lambda表达式*/
public void referenceTest() {
Function<String, Integer> stringToInteger = Integer::parseInt;
// (String s) -> Integer.parseInt(s);
BiPredicate<List<String>, String> contains = List::contains;
// (list, element) -> list.contains(element);
Supplier<Student> supplier = Student::new;
// () -> new Student()
}
}
Stream流
流
-
Colletion提供了新的Stream方法
-
Stream流不储存值,以管道的方式获取值
-
本质是函数式的,对流的操作会生成一个结果,不会改变底层的数据源,集合可以作为底层的数据源
特点
-
只能遍历一次
我们可以把流想象成一条流水线,流水线的源头是我们的数据源(一个集合),数据源中的元素依次被输送到流水线上,我们可以在流水线上对元素进行各种操作。一旦元素走到了流水线的另一头,那么这些元素就被“消费掉了”,我们无法再对这个流进行操作。当然,我们可以从数据源那里再获得一个新的流重新遍历一遍。
-
采用内部迭代
若要对集合进行处理,则需我们手写处理代码,这就叫做外部迭代。而要对流进行处理,我们只需告诉流我们需要什么结果,处理过程由流自行完成,这就称为内部迭代。
流的操作
- 中间操作(惰性取值,只有在终端方法调用才会执行)
当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。
- 终端操作(及早取值)
当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。
终端操作将返回一个执行结果,这就是你想要的数据。
流的操作过程
- 1 准备数据源
- 2 执行中间操作
中间操作可以有多个,它们可以串连起来形成流水线。
- 3 执行终端操坐
执行终端操作后本次流结束,你将获得一个执行结果。
- 创建stream流
/*创建Stream流*/
public void of() {
/*of方法 返回一个参数类型的stream 带有任意参数的集合*/
Stream<String> helloStream = Stream.of("hello", "world");
List<String> collectList = helloStream.map(e -> e.toUpperCase()).collect(Collectors.toList());
collectList.forEach(System.out::println);
/*创建一个不含任何原属的Stream*/
Stream<Object> empty = Stream.empty();
/*基本使用 数据源--中间操作--及早求值*/
List<Integer> list2 = Arrays.asList(1, 1, 2, 3, 4, 5, 6);
// System.out.println(list2.stream().map(e -> e + 2).reduce(Integer::sum).get());
}
- 生成无限的stream流
/*Stream接口两个用来创建无限Stream的静态方法*/
public void generateAndIterate() {
/*返回无限的无序stream流*/
Stream<String> generate = Stream.generate(() -> String.valueOf(3));
// generate.forEach(System.out::println);
/*返回无限的无序随机数字*/
Stream<Double> generate1 = Stream.generate(Math::random);
// generate1.forEach(System.out::println);
/*创建一个有序的stream流 {1,2,3,4...}*/
Stream<BigDecimal> iterate1 = Stream.iterate(BigDecimal.ZERO, e -> e.add(BigDecimal.ONE));
// iterate1.forEach(System.out::println);
}
Stream filter(Predicate<? super T> predicate)
filter方法的练习
/**
*author huangh
*date 2018/10/13 10:10
*description Predicate 接口的练习
*/
public class PredicateTest {
@Test
/***Stream API filter 的使用*
*返回满足Predicate的 Stream*
* @see Stream#filter(java.util.function.Predicate)
*/
public void filter(String username){
Person person1 = new Person("bob",21);
Person person2 = new Person("lily",21);
Person person3 = new Person("kevin",21);
List<Person> people = Arrays.asList(person1, person2, person3);
List<Person> filterPeople = people.stream().filter(e -> e.getUsername().equals(username))
.collect(Collectors.toList());
// filterPeople.forEach(e -> System.out.println(e));
System.out.println(filterPeople);
}
/**
* 对年龄的筛选
* BiFunction 给两个参数返回一个结果
* Stream API 对filter的使用
*/
public List<Person > filter(Integer age,List<Person> people) {
BiFunction<Integer,List<Person>, List<Person>> biFunction = (ageOfPerson,peopleList) ->
people.stream().filter(e ->e.getNum().equals(age)).collect(Collectors.toList());
return biFunction.apply(age,people);
}
/*先定义好行为的描述*/
public List<Person> filter (Integer age ,List<Person> people, BiFunction<Integer,List<Person>, List<Person>> biFunction){
return biFunction.apply(age,people);
}
public static void main(String[] args) {
Person person1 = new Person("bob",21);
Person person2 = new Person("lily",212);
Person person3 = new Person("kevin",213);
PredicateTest PredicateTest = new PredicateTest();
PredicateTest.filter("bob");
List<Person> people = Arrays.asList(person1, person2, person3);
List<Person> filter = PredicateTest.filter(212, people);
System.out.println(filter);
System.out.println("-------------------------------------");
/*先定义具体的行为 这样比前两个的方法 跟为灵活*/
List<Person> list = PredicateTest.filter(20,people,(ageOfPerson,personList) ->
people.stream().filter(e -> e.getNum()>20).collect(Collectors.toList())
);
System.out.println(list);
}
}
Stream 的短路 现象
public void fun() {
List<String> list = Arrays.asList("hello", "world", "welcome");
list.stream()
.map(e -> {
int length = e.length();
/*这里不会把每个都打印,会出现短路。只要符合条件则后面的元素都不执行*/
System.out.println(e);
return length;})
.filter(length -> length == 5)
.findFirst()
.ifPresent(System.out::println);
}
map 和 flatmap
@Test
public void flatMap() {
List<String> list = Arrays.asList("hello world", "hey new year", "welcome the world");
/*此处map会返回一个Stream<String[]> 然后再对其 去重*/
list.stream().map(string -> string.split(" ")).distinct().forEach(System.out::println);
/*先根据split分词,把Stream<String[]> 使用 flatMap(Arrays::stream) 转换为Stream<String> */
list.stream().map(string -> string.split(" ")).flatMap(Arrays::stream).
distinct().forEach(System.out::println);
}
Stream 和 ParallelStream
@Test
/*串行流 与 并发流*/
public void parallelStream(){
List<String> list = new ArrayList<>();
for (int i = 0;i<2000000;i++){
list.add(UUID.randomUUID().toString());
}
System.out.println("开始排序");
long start = System.nanoTime();
// list.stream().sorted().count(); 大约花费两秒
list.parallelStream().sorted().count(); //大约花费一秒
long end = System.nanoTime();
System.out.println(TimeUnit.NANOSECONDS.toMillis(end-start));
}