Java——Lambda表达式及运用
Lambda表达式是JDK1.8之后的新技术,核心目的是为了简化匿名内部类的代码写法
Lambda表达式使用前提:
-- 并不能简化所有匿名内部类的写法
-- 只能简化接口中只有一个抽象方法的匿名内部类形式,即只能简化只有一个抽象方法的函数式接口
@FunctionalInterface函数式接口注解:
-- 一旦加上了这个注解,这个接口只能有且只有一个抽象方法,这个接口可以被Lambda表达式简化
Lambda表达式简略写法:
-- 如果Lambda表达式的方法体只有一行代码,可以省略大括号不写,同时要省略分号
-- 如果Lambda表达式的方法体只有一行代码,可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
-- 参数类型可以省略不写
-- 如果只有一个参数,参数类型可以省略,同时()也可以省略
// 原型 Thread t = new Thread(new Runnable() { @Override public void run() { System.out.println("aaa"); } } t.start(); // 简化1 Thread t1 = new Thread(() -> { System.out.println("aaa"); }).start(); // 简化2 Thread t2 = new Thread(() -> System.out.println("aaa")).start();
静态方法引用
格式:类名::静态方法
要求:被引用的方法的参数列表要和函数式接口中的抽象方法的参数列表一致
public class MethodDemo { public static void main(String[] args) { List<Student> lists = new ArrayList<>(); Student s1 = new Student("李铭", 18, "男"); Student s2 = new Student("冯龙", 23, "男"); Student s3 = new Student("王乐乐", 21, "女"); Collections.addAll(lists, s1, s2, s3); System.out.println(lists); Collections.sort(lists, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }); // Lambda表达式简化参数二:匿名内部类的Comparator写法 Collections.sort(lists, (Student o1, Student o2) -> { return o1.getAge() - o2.getAge(); }); Collections.sort(lists, (o1, o2) -> o1.getAge() - o2.getAge()); Collections.sort(lists, (o1, o2) -> Student.compareByAge(o1, o2)); Collections.sort(lists, Student::compareByAge); } } @Data class Student { private String name; private int age; private String sex; Student(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } public static int compareByAge(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }
实例方法引用
// Lambda简化
lists.forEach( s -> System.out.println(s));
// 方法引用简化Lamdba表达式
lists.forEach( System.out::println);
特定类型方法引用
String[] strs = new String[]{"James", "aS", "ssd", "john", "dss"}; Arrays.sort(strs, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareToIgnoreCase(o2); } }); Arrays.sort(strs, ((o1, o2) -> o1.compareToIgnoreCase(o2))); Arrays.sort(strs, String::compareToIgnoreCase);
Stream流
作用:简化已有集合类库或者数组API的弊端
Stream流式思想的核心
1. 先得到集合或者数组的Stream流(就是一根传送带)
2. 然后就用Stream流操作集合或者数组的元素
3. 然后用Stream流简化集合操作的API
Stream流的常用API
forEach:逐一处理(遍历)(终结方法,一旦调用,流操作结束)
count:统计个数 -- long count()(终结方法,一旦调用,流操作结束)
filter:过滤元素 -- Stream<T> filter(Predicate<? super T> predicate)
limit:取前几个元素
skip:跳过前几个
map:加工方法
concat:合并流
public class StreamDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); list.add("张无忌"); list.add("周芷若"); list.add("张三丰"); list.add("洪七公"); list.add("赵敏"); list.add("张强"); list2.add(2); List<String> zhangLists = new ArrayList<>(); for (String s: list) { if (s.startsWith("张")){ zhangLists.add(s); } } List<String> zhangThreeLists = new ArrayList<>(); for (String s: zhangLists) { if (s.length() == 3){ zhangThreeLists.add(s); } } System.out.println(zhangLists); System.out.println(zhangThreeLists); list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println); list.stream().map(s-> s + "测试").limit(4).forEach(System.out::println); Stream<Object> allStream = Stream.concat(list.stream(), list2.stream()); allStream.forEach(System.out::println); } }
收集流
实际开发中数据最终的形式还是应该是集合,因此需要把stream流的数据转回到集合中去
Stream<String> zhangList = list.stream().filter(s -> s.startsWith("张")); // 转换成Set集合 Set<String> sets = zhangList.collect(Collectors.toSet()); System.out.println(sets); // 转换成List集合 Stream<String> zhangList2 = list.stream().filter(s -> s.startsWith("张")); List<String> lists3 = zhangList2.collect(Collectors.toList()); System.out.println(lists3); // 转换成数组 Stream<String> zhangList3 = list.stream().filter(s -> s.startsWith("张")); // Object[] arr1 = zhangList3.toArray(); String[] arr2 = zhangList3.toArray(String[]::new);