forEach + lambda 表达式
循环 Map
Map<String, Integer> items = new HashMap<>(); items.put("A", 10); items.put("B", 20); items.put("C", 30); items.put("D", 40); items.put("E", 50); items.put("F", 60); items.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v)); items.forEach((k,v)->{ System.out.println("Item : " + k + " Count : " + v); if("E".equals(k)){ System.out.println("Hello E"); } });
循环 List
List<String> items = new ArrayList<>(); items.add("A"); items.add("B"); items.add("C"); items.add("D"); items.add("E"); //lambda //Output : A,B,C,D,E items.forEach(item->System.out.println(item)); //Output : C items.forEach(item->{ if("C".equals(item)){ System.out.println(item); } }); //method reference //Output : A,B,C,D,E items.forEach(System.out::println); //Stream and filter //Output : B items.stream() .filter(s->s.contains("B")) .forEach(System.out::println);
注意:lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
方法引用
方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。
简单地说,就是一个Lambda表达式。在Java 8中,我们会使用Lambda表达式创建匿名方法,但是有时候,我们的Lambda表达式可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰,Java 8的方法引用允许我们这样做。方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。
jdk8中方法引用使用一对冒号::。就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下,双冒号运算就是Java中的[方法引用],[方法引用]的格式是:类名::方法名
方法引用分类
先来说一下方法引用使用到的操作符“::”,这个操作符把方法引用分成两边,左边是类名或者某个对象的引用,右边是方法名。引用方法有下面几种方式:
(1)对象引用::实例方法名
(2)类名::静态方法名
(3)类名::实例方法名
(4)类名::new
(5)类型[]::new
public class Student { private String name; private int score; public Student(){ } public Student(String name,int score){ this.name = name; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } public static int compareStudentByScore(Student student1,Student student2){ return student1.getScore() - student2.getScore(); } public static int compareStudentByName(Student student1,Student student2){ return student1.getName().compareToIgnoreCase(student2.getName()); } public int compareByScore(Student student){ return this.getScore() - student.getScore(); } }
对象引用::实例方法名
StudentComparator studentComparator = new StudentComparator(); students.sort(studentComparator::compareStudentByScore); students.forEach(student -> System.out.println(student.getScore()));
类名::静态方法名
students.sort(Student::compareStudentByScore);
students.forEach(student -> System.out.println(student.getScore()));
类名::实例方法名
students.sort(Student::compareByScore);
students.forEach(student -> System.out.println(student.getScore()));
类名::new
Supplier<Student> supplier = Student::new;
类型[]::new
//使用数组构造器创建数组 ArrayBuilder ab2 = int[]::new; int[] arr2 = ab2.buildArray(5); System.out.println("创建的数组 2:" + Arrays.toString(arr2));
Optional
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
of
根据传入的值生成Optional对象
of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。
User u1 = new User(); User u2 = new User(); u2.setName("张三"); User u3 = null; Optional<User> user1 = Optional.of(u1); Optional<User> user2 = Optional.of(u2); // 打印空user对象 log.info("user1:" + user1.toString()); // 打印name = 张三的user对象 log.info("user2:" + user2.toString()); // NullPointerException Optional<User> user3 = Optional.of(u3);
ofNullable
根据传入的值生成Optional对象
如果指定的值为null,则返回一个空的Optional。
User u1 = new User(); User u2 = new User(); u2.setName("张三"); User u3 = null; Optional<User> user1 = Optional.ofNullable(u1); Optional<User> user2 = Optional.ofNullable(u2); Optional<User> user3 = Optional.ofNullable(u3); // 打印空user对象 log.info("user1:" + user1.toString()); // 打印name = 张三的user对象 log.info("user2:" + user2.toString()); // 打印empty log.info("user3:" + user3.toString());
get
如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
User u2 = new User(); u2.setName("张三"); User u3 = null; User user2 = Optional.ofNullable(u2).get(); // 打印name = 张三的user对象 log.info("user2:" + user2); // NoSuchElementException User user3 = Optional.ofNullable(u3).get(); log.info("user3:" + user3);
isPresent
如果有值返回true,如果为null返回false。
User u2 = new User(); u2.setName("张三"); User u3 = null; boolean booleanUser2 = Optional.ofNullable(u2).isPresent(); boolean booleanUser3 = Optional.ofNullable(u3).isPresent(); // true log.info("booleanUser2:" + booleanUser2); // false log.info("booleanUser3:" + booleanUser3);
ifPrensent
该方法也可以检测是否为null,同时该方法还可以接受一个Consumer参数。
User u2 = new User(); u2.setName("张三"); Optional.ofNullable(u2).ifPresent(user -> user.setAge(21)); // 21 log.info("u2:" + u2.getAge());
orElse
如果有值则将其返回,否则返回指定的其它值。
User u2 = new User(); u2.setName("张三"); User u3 = null; User user = Optional.ofNullable(u3).orElse(u2); // 打印u2对象 log.info("user:" + user.toString());
orElseGet
orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。
User u2 = new User(); u2.setName("张三"); User u3 = null; User user1 = Optional.ofNullable(u3).orElseGet(() -> new User()); User user2 = Optional.ofNullable(u3).orElseGet(() -> u2); // 打印User空对象 log.info("user1:" + user1.toString()); // u2对象 log.info("user2:" + user2.toString());
备注:orElse和orElseGet区别:当user对象不为null时,orElse能创建User对象,而orElseGet方法不创建User对象。
orElseThrow
如果有值则将其返回,否则抛出supplier接口创建的异常。
User u1 = null; User u2 = new User(); u2.setName("张三"); User user2 = Optional.ofNullable(u2).orElseThrow(() -> new IllegalStateException()); // 打印u2对象 log.info("user2:" + user2.toString()); // IllegalStateException User user1 = Optional.ofNullable(u1).orElseThrow(() -> new IllegalStateException());
map
如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
map方法用来对Optional实例的值执行一系列操作。通过一组实现了Function接口的lambda表达式传入操作。
User u1 = new User(); u1.setName("张三"); User u2 = new User(); u2.setName("李四"); u2.setEmail("lisi@163.com"); Optional<String> s = Optional.ofNullable(u1).map(user -> user.getEmail()); String email1 = s.orElse("zhangsan@sina.com"); // zhangsan@sina.com log.info("email1:" + email1); String email2 = Optional.ofNullable(u2).map(user -> user.getEmail()).orElse("lisi@hotmail.com"); // lisi@163.com log.info("email2:" + email2);
flatMap
如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。
flatMap方法与map方法类似,区别在于mapping函数的返回值不同。map方法的mapping函数返回值可以是任何类型T,而flatMap方法的mapping函数必须是Optional。
User u1 = new User(); u1.setName("张三"); String name = Optional.ofNullable(u1).flatMap(user -> user.getName()).orElse("zhangsan"); // 张三 log.info("name:" + name);
filter
如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
User user = new User(); user.setName("张三"); user.setAge(11); User user1 = Optional.ofNullable(user).filter(u -> u.getName().equals("张三") && u.getAge() == 11).orElseThrow(() -> new NullPointerException()); // user对象 log.info("user1:" + user1); // NullPointerException User user2 = Optional.ofNullable(user).filter(u -> u.getName().equals("张三") && u.getAge() == 22).orElseThrow(() -> new NullPointerException()); log.info("user2:" + user2);
综合应用
CustomListResult customListResult = customListParamMapper.getCustomListByMenuName(customListParam); Optional.ofNullable(customListResult).ifPresent(result -> { result.setMenus(JSON.parseArray(customListResult.getMenuArr())); });