Java8新特性 Lambda、Stream、Optional实现原理
Java8新特性 Lambda、Stream、Optional实现原理
- 一、接口中默认方法修饰为普通方法
- 二、Lambda表达式
- 2.1、什么是Lambda表达式
- 2.2、为什么要使用Lambda表达式
- 2.3、Lambda表达式的规范
- 2.4、函数接口定义
- 2.5、Java系统内置那些函数接口
- 2.5.1、消费型接口:
- 2.5.2、供给型接口
- 2.5.3、函数型接口
- 2.5.4、断言型接口
- 2.6、Lambda基础语法
- 2.6.1、无参方法调用
- 2.6.2、带参数和返回值
- 2.7、方法引入
- 2.7.1、什么是方法引入
- 2.7.2、方法引入
- 2.7.2.1、方法引入规则
- 2.7.2.2、静态方法引入
- 2.7.2.3、对象方法引入
- 2.7.2.4、实例方法引入
- 2.7.2.5、构造函数引入
- 2.8、Lambda实战案例
- 2.8.1、Foreach
- 2.8.2、Lambda集合排序
- 2.8.3、线程调用
- 三、Stream流
- 3.1、什么是Stream流
- 3.2、Stream创建方式
- 3.3、Stream将list转换为Set
- 3.4、Stream将list转换为Map
- 3.5、Stream将Reduce 求和
- 3.6、StreamMax和Min
- 3.7、StreamMatch 匹配
- 3.8、StreamFor循环
- 3.9、Stream过滤器
- 3.10、Stream排序 sorted
- 3.11、Stream limit和skip
- 3.12、并行流与串行流区别
- 四、JDK8 Optional
- 4.1、判断参数是否为空
- 4.2、参数为空可以设定默认值
- 4.3、参数实现过滤
- 4.4、与Lambda表达式结合使用,优化代码
- 4.4.1、优化方案1
- 4.4.2、优化方案2
- 4.4.3、优化方案3
一、接口中默认方法修饰为普通方法
在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的,由于这些修饰符都是默认的。
接口定义方法:public 抽象方法 需要子类实现
接口定义变量:public、static、final
在JDK 1.8开始 支持使用static和default 修饰 可以写方法体,不需要子类重写。
方法:
- 普通方法 可以有方法体
- 抽象方法 没有方法体需要子类实现 重写。
二、Lambda表达式
2.1、什么是Lambda表达式
Lambda 好处:
- 简化我们匿名内部类的调用。
- Lambda + 方法引入 代码变得更加精简。
- Lambda 表达式(lambda expression)是一个匿名函数,简化我们调用匿名函数的过程。
2.2、为什么要使用Lambda表达式
可以非常简洁的形式调用我们的匿名函数接口。
OrderService
public interface OrderService {void addOrder();
}
OrderServiceImpl
public class OrderServiceImpl implements OrderService {@Overridepublic void addOrder() {System.out.println("添加订单");}
}
Test01
public static void main(String[] args) {//1.使用new的实现类的形式调用接口OrderService orderService = new OrderServiceImpl();orderService.addOrder();//2.使用匿名内部接口调用new OrderService() {@Overridepublic void addOrder() {System.out.println("使用匿名内部类的形式调用接口");}}.addOrder();// 3.使用lambda调用接口OrderService orderService2 = () -> System.out.println("使用lambda调用接口");orderService2.addOrder();}
2.3、Lambda表达式的规范
使用Lambda表达式 依赖于函数接口
- 在接口中只能够允许有一个抽象方法
- 在函数接口中定义object类中方法
- 使用默认或者静态方法
- @FunctionalInterface 表示该接口为函数接口
Java中使用Lambda表达式的规范,必须是为函数接口
函数接口的定义:
- 在该接口中只能存在一个抽象方法,该接口称作为函数接口
JDK中自带的函数接口:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
我们也可以使用@FunctionalInterface修饰为函数接口
2.4、函数接口定义
- 在接口中只能有一个抽象方法
- @FunctionalInterface 标记为该接口为函数接口
- 可以通过default 修饰为普通方法
- 可以定义object类中的方法
@FunctionalInterface
public interface MyFunctionalInterface {void add();default void get(){}String toString();
}
2.5、Java系统内置那些函数接口
2.5.1、消费型接口:
- Conusmer
void accept(T t); - BiConusmer<T,U>
void accept(T t,U u);//增加一种入参类型
2.5.2、供给型接口
- Supplier
void get();
2.5.3、函数型接口
- Function<T ,R>
R apply(T t); - UnaryOperator
T apply(T t);//入参与返回值类型一致 - BiFunction <T ,U,R>
R apply(T t,U u);//增加一个参数类型 - BinaryOperator
T apply(T t1,T t2);//l两个相同类型入参与同类型返回值 - ToIntFunction//限定返回int
- ToLongFunction//限定返回long
- ToDoubleFunction//限定返回double
- IntFunction//限定入参int,返回泛型R
- LongFunction//限定入参long,返回泛型R
- DoubleFunction//限定入参double,返回泛型R
2.5.4、断言型接口
- Predicate
- boolean test(T t)
2.6、Lambda基础语法
语法格式一: 无参数,无返回值。 () -> { }
Runnable runnable = () -> System.out.print("Hello Lambda");
语法格式二: 有一个参数,并且无返回值。 (x) ->{ }
Consumer<String> consumer = (x) -> System.out.print("Hello Lambda");
语法格式三: 有两个以上参数,有返回值, 并且Lambda式中有多条语句。
Comparator<Integer> comparator = (x, y) -> {System.out.print("Hello Lambda");return Integer.compare(x,y);
};
若Lambda体中只有一条语句,return 和 大括号都可以省略不写。
Lambda表达式参数列表的数据类型可以省略不写,因为JVM的编译器通过上下文可以推断出类型,即 “类型推断”
Lambda表达式需要“函数式接口”的支持。
函数式接口: 接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface修饰 来检查是否是函数式接口。
2.6.1、无参方法调用
AcanthopanaxInterface
public interface AcanthopanaxInterface {void get();
}
Test
public class Test06 {public static void main(String[] args) {AcanthopanaxInterface acanthopanaxInterface = () -> System.out.println("使用lamdba表达式调用方法");acanthopanaxInterface.get();}
}
2.6.2、带参数和返回值
YouCanInterface
public interface YouCanInterface {String get(int i, int j);
}
Test07
public class Test07 {public static void main(String[] args) {YouCanInterface youCanInterface = new YouCanInterface() {@Overridepublic String get(int i, int j) {return i + "----" + j;}};System.out.println(youCanInterface.get(2, 3));}
}
精简语法
public class Test07 {public static void main(String[] args) {YouCanInterface youCanInterface = (i, j) -> i + "----" + j;System.out.println(youCanInterface.get(2, 3));}
}
2.7、方法引入
2.7.1、什么是方法引入
需要结合lambda表达式能够让代码变得更加精简。
- 匿名内部类使用
- Lambda调用匿名内部类
- 方法引入
2.7.2、方法引入
- 静态方法引入: 类名::(静态)方法名称
- 对象方法引入 类名:: 实例方法名称
- 实例方法引入 new对象 对象实例::方法引入
- 构造函数引入 类名::new
需要遵循一个规范:
方法引入 方法参数列表、返回类型与函数接口参数列表与返回类型必须
要保持一致。
Lambda: 匿名内部类使用代码简洁问题
类型 | 语法 | 对应lambda表达式 |
---|---|---|
构造器引用 | Class::new | (args) -> new 类名(args) |
静态方法引用 | Class::static_method | (args) -> 类名.static_method(args) |
对象方法引用 | Class::method (inst,args) | (inst,args) -> 类名.method(args) |
实例方法引用 | instance::method (args) | (args) -> instance.method(args) |
方法引用提供了非常有用的语法,可以直接引用已有的java类或对象的方法或构造器。方法引用其实也离不开Lambda表达式,
与lambda联合使用 ,方法引用可以使语言的构造更加紧凑简洁,减少冗余代码。
方法引用提供非常有用的语法,可以直接引用已有的java类或者对象中方法或者构造函数,
方法引用需要配合Lambda表达式语法一起使用减少代码的冗余性问题。
2.7.2.1、方法引入规则
方法引入实际上就是lambda表达式中直接引入的方法。
必须遵循规范:引入的方法参数列表返回类型必须要和函数接口参数列表、返回
类型保持一致。
2.7.2.2、静态方法引入
MessageInterface
@FunctionalInterface
public interface MessageInterface {void get();
}
MethodReference
public class MethodReference {public static void main(String[] args) {//1.使用匿名内部类的形式 调用get方法new MessageInterface() {@Overridepublic void get() {MethodReference.getMethod();}}.get();//2.使用lambda((MessageInterface) () -> MethodReference.getMethod()).get();// 使用方法引入调用方法 必须满足:方法引入的方法必须和函数接口中的方法参数列表/返回值一定保持一致。MessageInterface messageInterface = MethodReference::getMethod;messageInterface.get();}public static void getMethod() {System.out.println("我是getMethod");}
}
2.7.2.3、对象方法引入
ObjectMethodService
public interface ObjectMethodService {String get(Test08 test08);
}
Test08
public class Test08 {public static void main(String[] args) {// 1.使用匿名内部类的形式ObjectMethodService objectMethodService = new ObjectMethodService() {@Overridepublic String get(Test08 test08) {return test08.objGet();}};System.out.println(objectMethodService.get(new Test08()));// 2.lambdaObjectMethodService objectMethodService1 = test08 -> test08.objGet();System.out.println(objectMethodService1.get(new Test08()));// 3.方法引入 在这时候我们函数接口 第一个参数传递test23 返回调用test23.objGet方法//Test08::objGet; == (test08) -> test08.objGet();ObjectMethodService objectMethodService2 = Test08::objGet;System.out.println(objectMethodService2.get(new Test08()));// 需要将string类型字符串获取长度Function<String, Integer> function2 = String::length;System.out.println(function2.apply("hello world"));}public String objGet() {return "hello world";}
}
2.7.2.4、实例方法引入
MessageInterface2
@FunctionalInterface
public interface MessageInterface2 {void get(Integer a);
}
Test09
public class Test09 {public static void main(String[] args) {//1.匿名内部类的写法Test09 test09 = new Test09();MessageInterface2 messageInterface = new MessageInterface2() {@Overridepublic void get(Integer a) {test09.get(a);}};messageInterface.get(6);//lambdaMessageInterface2 messageInterface2 = a -> test09.get(a);}public void get(Integer a) {System.out.println("方法引入get方法:" + a);}
}
2.7.2.5、构造函数引入
User
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String name;private Integer age;
}
UserInterface
public interface UserInterface {User getUser();
}
Test10
public class Test10 {public static void main(String[] args) {//1.匿名内部类UserInterface userInterface = new UserInterface() {@Overridepublic User getUser() {return new User();}};System.out.println(userInterface.getUser());//lambdaUserInterface userInterface2 = () -> new User();System.out.println(userInterface2.getUser());//构造函数UserInterface userInterface3 = User::new;System.out.println(userInterface3.getUser());}
}
2.8、Lambda实战案例
2.8.1、Foreach
public class Test03 {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("java");list.add("php");list.add("python");list.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println("s = " + s);}});System.out.println("=================");list.forEach((String s)-> System.out.println("s = " + s));}
}
2.8.2、Lambda集合排序
User
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String name;private Integer age;
}
Test04
public class Test04 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("zhangsan", 26));userList.add(new User("lisi", 18));userList.add(new User("wagnwu", 23));userList.sort(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return o1.getAge() - o2.getAge();}});System.out.println("userList = " + userList);System.out.println("=========");userList.sort((User o1, User o2) -> o2.getAge() - o1.getAge());System.out.println("userList = " + userList);System.out.println("=========");}
}
2.8.3、线程调用
public class Test05 {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + ",线程执行了");}}).start();new Thread(() -> System.out.println(Thread.currentThread().getName() + ",线程执行了")).start();}
}
三、Stream流
3.1、什么是Stream流
Stream 是JDK1.8 中处理集合的关键抽象概念,Lambda 和 Stream 是JDK1.8新增的函数式编程最有亮点的特性了,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Stream :非常方便精简的形式遍历集合实现 过滤、排序等。
3.2、Stream创建方式
parallelStream为并行流采用多线程执行
Stream采用单线程执行
parallelStream效率比Stream要高。
public class Test11 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();Stream<User> userStream = userList.parallelStream();}
}
3.3、Stream将list转换为Set
Test11
public class Test11 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();Set<User> set = stream.collect(Collectors.toSet());System.out.println("set = " + set);}
}
3.4、Stream将list转换为Map
public class Test12 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();Map<String, User> collect = stream.collect(Collectors.toMap(new Function<User, String>() {@Overridepublic String apply(User user) {return user.getName();}}, new Function<User, User>() {@Overridepublic User apply(User user) {return user;}}));collect.forEach(new BiConsumer<String, User>() {@Overridepublic void accept(String key, User user) {System.out.println("key = " + key + ", value = " + user);}});}
}
3.5、Stream将Reduce 求和
public class Test13 {public static void main(String[] args) {Stream<Integer> integerStream = Stream.of(10, 20, 50, 45, 48, 56, 19);
// Optional<Integer> reduce = integerStream.reduce(new BinaryOperator<Integer>() {// @Override
// public Integer apply(Integer integer, Integer integer2) {// return integer + integer2;
// }
// });Optional<Integer> reduce = integerStream.reduce((integer, integer2) -> integer + integer2);System.out.println(reduce.get());List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();
// Optional<User> reduce1 = stream.reduce(new BinaryOperator<User>() {// @Override
// public User apply(User user, User user2) {// user.setAge(user.getAge() + user2.getAge());
// return user;
// }
// });Optional<User> reduce1 = stream.reduce((user, user2) -> {user.setAge(user.getAge() + user2.getAge());return user;});System.out.println("reduce1 = " + reduce1);}
}
3.6、StreamMax和Min
public class Test14 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();
// Optional<User> maxUser = stream.max(new Comparator<User>() {// @Override
// public int compare(User o1, User o2) {// return o1.getAge() - o2.getAge();
// }
// });Optional<User> maxUser = stream.max((o1, o2) -> o1.getAge() - o2.getAge());System.out.println(maxUser.get());//流被关闭 重新打开stream = userList.stream();Optional<User> minUser = stream.min((o1, o2) -> o1.getAge() - o2.getAge());System.out.println(minUser.get());}
}
3.7、StreamMatch 匹配
anyMatch表示,判断的条件里,任意一个元素成功,返回true
allMatch表示,判断条件里的元素,所有的都是,返回true
noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
public class Test15 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();
// boolean result = stream.noneMatch(new Predicate<User>() {// @Override
// public boolean test(User user) {// return user.getAge() > 99999;
// }
// });boolean result = stream.noneMatch(user -> user.getAge() > 99999);System.out.println("result = " + result);}
}
3.8、StreamFor循环
public class Test16 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();// stream.forEach(new Consumer<User>() {// @Override
// public void accept(User user) {// System.out.println("user = " + user);
// }
// });stream.forEach(user -> System.out.println("user = " + user));}
}
3.9、Stream过滤器
public class Test17 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));userList.add(new User("斗战圣佛", 1000));Stream<User> stream = userList.stream();// stream.filter(new Predicate<User>() {// @Override
// public boolean test(User user) {// return user.getAge() < 10000;
// }
// }).filter(new Predicate<User>() {// @Override
// public boolean test(User user) {// return user.getName().equals("斗战圣佛");
// }
// }).forEach(new Consumer<User>() {// @Override
// public void accept(User user) {// System.out.println("user = " + user);
// }
// });stream.filter(user -> user.getAge() < 10000).filter(user -> user.getName().equals("斗战圣佛")).forEach(user -> System.out.println("user = " + user));}
}
3.10、Stream排序 sorted
public class Test18 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();
// stream.sorted(new Comparator<User>() {// @Override
// public int compare(User o1, User o2) {// return o1.getAge() - o2.getAge();
// }
// }).forEach(new Consumer<User>() {// @Override
// public void accept(User user) {// System.out.println("user = " + user);
// }
// });stream.sorted((o1, o2) -> o1.getAge() - o2.getAge()).forEach(user -> System.out.println("user = " + user));}
}
3.11、Stream limit和skip
Limit 从头开始获取
Skip 就是跳过
public class Test19 {public static void main(String[] args) {List<User> userList = new ArrayList<>();userList.add(new User("东来佛组", 200000));userList.add(new User("如来佛组", 100000));userList.add(new User("未来佛组", 50000));userList.add(new User("斗战圣佛", 600));Stream<User> stream = userList.stream();stream.skip(2).limit(1).forEach(user -> System.out.println("user = " + user));}
}
3.12、并行流与串行流区别
串行流:
- 单线程的方式操作; 数据量比较少的时候。
并行流:
- 多线程方式操作;数据量比较大的时候,原理:
Fork join 将一个大的任务拆分n多个小的子任务并行执行,
最后在统计结果,有可能会非常消耗cpu的资源,确实可以
提高效率。
注意:数据量比较少的情况下,不要使用并行流。
四、JDK8 Optional
- Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
- Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
- Optional 类的引入很好的解决空指针异常。
4.1、判断参数是否为空
ofNullable(可以传递一个空对象)
of(不可以传递空对象,传null会报NullPointerException)
Integer a = 1;
Optional<Integer> result = Optional.ofNullable(a);
System.out.println(result.isPresent());
- isPresent true 不为空
- isPresent返回 false 为空。
4.2、参数为空可以设定默认值
Integer a = 1;
Optional<Integer> result = Optional.ofNullable(a);
System.out.println(result.get());
System.out.println(result.isPresent());
a = null;
Integer rs = Optional.ofNullable(a).orElse(2);
System.out.println(rs);
4.3、参数实现过滤
Integer val = 16;
Optional<Integer> result = Optional.ofNullable(val);
boolean isPresent = result.filter(a2 -> a2 > 17).isPresent();
System.out.println(isPresent);
4.4、与Lambda表达式结合使用,优化代码
4.4.1、优化方案1
// 优化前
String name = "hello";
if (name != null) {System.out.println(name);
}
//优化后
Optional<String> name2 = Optional.ofNullable(name);
// 当value 不为空时,则不会调用
//name2.ifPresent(s -> System.out.println(s));
name2.ifPresent(System.out::print);
4.4.2、优化方案2
public class Test26 {private static User user = null;public static void main(String[] args) {User user = Test26.getUser();System.out.println(user);}public static User getUser() {// 优化前
// if (user == null){// return createUser();
// }
// return user;// 优化后
// return Optional.ofNullable(user).orElseGet(new Supplier<User>() {// @Override
// public User get() {// return createUser();
// }
// });return Optional.ofNullable(user).orElseGet(() -> createUser());}private static User createUser() {return new User("java", 25);}
}
4.4.3、优化方案3
map中获取的返回值自动被Optional包装,即返回值 -> Optional<返回值>
flatMap中返回值保持不变,但必须是Optional类型,即Optional<返回值> -> Optional<返回值>
public class Test27 {public static void main(String[] args) {String name = Test27.getName();System.out.println(name);}public static String getName() {User user = new User("Java521", 66);// 优化前写法:
// if (user != null) {// String name = user.getName();
// if (name != null) {// return name.toLowerCase();
// }
// }
// return null;//优化后写法:return Optional.ofNullable(user).map(user1 -> {return user1.getName();}).map(name -> {return name.toLowerCase();}).orElse(null);}
}
Java8新特性 Lambda、Stream、Optional实现原理相关推荐
- 使用Java8新特性(stream流、Lambda表达式)实现多个List 的笛卡尔乘积 返回需要的List<JavaBean>
需求分析: 有两个Long类型的集合 : List<Long> tagsIds; List<Long> attributesIds; 现在需要将这两个Long类型的集合进行组合 ...
- 【java8新特性】——Stream API详解(二)
一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...
- Java8新特性----Lambda表达式详细探讨
Java8新特性 Lambda表达式 入门演示 案例1 如何解决 cannot be cast to java.lang.Comparable问题? 案例2 优化方式一 : 策略设计模式 优化方式二: ...
- java8新特性-lambda表达式入门学习
定义 jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expressi ...
- Java8新特性:Stream介绍和总结
Java8新特性:Stream介绍和总结 什么是Stream 流(Stream)是数据渠道,用于操作数据源(集合.数组等)所生成的元素序列. 集合讲的是数据,流讲的是计算 注意: Stream自己不会 ...
- java stream byte_乐字节-Java8新特性之Stream流(上)
上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...
- Java8新特性总结 - 2.Optional类
所有示例代码打包下载 : 点击打开链接 Java8新特性 : 接口新增默认方法和静态方法 Optional类 Lambda表达式 方法引用 Stream API - 函数式操作流元素集合 Date/ ...
- java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量
一提到java是一种什么语言? 大多数人肯定异口同声的说是一门面向对象的语言,这种观点从我们开始学java就已经根深蒂固了,但是学到java8新特性函数式编程的时候,我才知道java并不是纯面向对象的 ...
- Java8新特性-使用Stream流来实现递归遍历树形结构(案例)
Java8新特性-Stream流 可能平常会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来 ...
最新文章
- 你能用上降噪耳机,竟要感谢傅立叶变换?
- 干货丨人工智能、大数据领域从菜鸟到高手的晋级指南(经典长文,值得收藏)
- 用 Heapster 监控集群 - 每天5分钟玩转 Docker 容器技术(176)
- 【深度学习】Dropout、正反向传播、计算图等的介绍和实现(Pytorch)
- 2018年中国研究生数学建模竞赛C题 二等奖 赛题论文
- 腾讯助力贵阳市智慧升级 共同探索创新型城市发展
- [C#]泛型与非泛型集合类的区别及使用例程,包括ArrayList,Hashtable,ListT,DictionaryTkey,Tvalue,SortedListTkey,Tvalue,...
- matlab中右三角形方向,《有限元基础教程》_【MATLAB算例】4.7.1(2) 基于3节点三角形单元的矩形薄板分析(Triangle2D3Node)...
- python的requests快速上手、高级用法和身份认证
- 在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView
- wpf image控件循环显示图片 以达到动画效果 问题及解决方案
- 【nginx系列】深入理解nginx原理
- 面向对象:寻寻觅觅,诚邀你一起来解开这道迷题
- 抖音互关源码 E4A源码含数据库后台程序搭建可用
- 三网融合融什么融,团购网站团什么团【涂雅速涂】
- 【python做接口测试的学习记录day9——pytest自动化测试框架之yaml数据驱动封装】
- Linux错误:bash:finger 未找到命令...
- 基于JAVA工作流流程编辑OA系统计算机毕业设计源码+数据库+lw文档+系统+部署
- php把文字写到图片生成
- 2014华为实习生招聘机试题
热门文章
- 求1000的阶乘尾部0的个数
- 离散数学_第二章:基本结构:集合、函数、序列、求和和矩阵(1)
- seo关键词的选取原则,关键词的拓展方法,关键词的分析筛选
- 众昂矿业:萤石矿现状如何?
- 久而久之的伤感心情日志发布:爱上一个不该爱的人
- 自动最后一英里交付的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- 利用Python实现图像的二值化
- 2014春江苏省计算机二级vb笔试考试真题详细讲解,2013春江苏省计算机二级VB笔试考试真题...
- 学院旅行计算机学院,计算机学院学生会 | 关于我们,你所不知道的……
- jar文件运行时 Failed to load Main-Class manifest attribute from