Java中lambda表达式的使用(一)+https://developer.aliyun.com/article/1413557
4.lambda表达式中的变量捕获
lambda表达式可以看作对匿名内部类进行的语法上的精简,同时也可以进行变量的捕获
@FunctionalInterface interface DemoTest { void func(); }
当使用被修改过的变量 -->依然报错
尽量使用被final修饰的变量
引用类变量
@FunctionalInterface interface DemoTest { void func(); } public class Demo10 { // 使用类变量 可以直接访问 public static int a = 10; public static void main(String[] args) { // lambda表达式 DemoTest demoTest = () -> { System.out.println(a); }; }
对于类变量来说,在lambda表达式中可以直接引用,因为类变量是属于类的,是所有对象公用的,它本身就有"静态"的属性
五.在优先级队列中的使用
优先级队列中往往涉及到比较,我们在实例化优先级队列的时候往往要传递一个比较器,规定比较的对象
// 使用匿名内部类实现Comparator接口 PriorityQueue<Integer> priorityQueue = new PriorityQueue(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } });
其实也能看出,Comparator方法应该是一个函数式接口,它属于"多个参数,有返回值"的类型(对应于上面的最后一种情况),此处就可以使用lambda表达式进行语法上的精简
// 使用lambda表达式实现优先级队列中的比较 PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1,o2) ->{return o1-o2;});
Comparator的源码 -->多个参数,有返回值的接口
六.创建线程
创建线程的方式有很多种,可以采用匿名内部类,lambda表达式
1.匿名内部类创建线程
// 创建线程 ->使用匿名内部类 Thread thread1 = new Thread() { @Override public void run() { System.out.println("hello thread"); } }; // 这种方式可以降低耦合性(推荐) Thread thread2 = new Thread(new Runnable() { @Override public void run() { System.out.println("hello thread2"); } });
为什么可以使用匿名内部类创建一个线程呢?主要是因为Thread类实现了Runnable接口,这个接口是一个函数式接口,只有一个抽象方法run()
2.使用lambda表达式
既然Thread可以通过匿名内部类方式创建线程,同时就可以使用lambda表达式来简化创建
// 方式1 Thread thread1 = new Thread(() ->{ System.out.println("hello thread1"); }); thread1.run();// 输出hello thread1 //方式2 利用lambda表达式实例化一个runnable接口 降低耦合性 Runnable runnable = () -> System.out.println("hello thread2"); Thread thread2 = new Thread(runnable); thread2.run();// 输出hello thread2
七.lambda表达式在集合类中的使用(以后最常用的一种)
为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与Lambda表达式对 接。
1.Collection接口
1.1forEach()
1.源码
forEach()在Iterable接口之下,源码如下:
default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
对传入的集合的每个元素执行action操作,进一步观察
可以观察到。forEach()方法接受了一个Comsumer类型的参数action,接着会对每一个action执行对应的操作。Consumer是一个函数式接口,属于"一个参数但无返回值"的类型,内部有一个抽象方法accept用于接受参数并执行特定的操作
2.使用匿名内部类实现
List<String> list = new ArrayList<>(); list.add("hello"); list.add("my"); list.add("friends"); list.add("!!!"); list.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.print(s + " "); } });
3.使用lambda表达式
// lambda表达式 list.forEach((s) -> System.out.print(s + " "));
1.2removeif()
removeif()用于根据条件删除集合中的对应数据,如果有对应条件的数据,删除,并将标志位removed设置为true(注意:removeif不是只删除一个符合条件的数据,而是类似于removeAll一样的效果)
1.源码:
default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; }
2.图解:
3.使用
List<String> list = new ArrayList<>(); list.add("hello"); list.add("my"); list.add("friends"); list.add("!!!"); // 1.先打印原数据 list.forEach((s) -> System.out.print(s + " ")); // 2.删除长度 <= 3的字符串 boolean flg = list.removeIf(new Predicate<String>() { @Override public boolean test(String s) { return s.length() <= 3; } }); System.out.println(""); // 3.判断是否有删除操作 System.out.println(flg); // 4.打印删除之后的数据 list.forEach((s) -> System.out.print(s + " "));
打印结果:
2.List接口
2.1 sort
1.源码:
default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }
2.图解:
3.使用:
List<String> list = new ArrayList<>(); list.add("hello"); list.add("my"); list.add("friends"); list.add("!!!"); // 使用匿名内部类 list.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2);// 从小到大排序 } }); // 使用lambda表达式 list.sort((o1,o2) -> { return o1.compareTo(o2); }); list.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.print(s + " "); } });
打印结果:
2.2 reolaceAll
1.源码:
default void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final ListIterator<E> li = this.listIterator(); while (li.hasNext()) { li.set(operator.apply(li.next())); } }
2.图解:
3.使用:
List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); // 打印原数据 System.out.println(list.toString()); // 使用匿名内部类 list.replaceAll(new UnaryOperator<Integer>() { @Override public Integer apply(Integer integer) { return integer*2;// 将所有的值都设置为原来的两倍 } }); // 使用lambda表达式 list.replaceAll((x) ->{return x*2;}); // 打印修改之后的数据 System.out.println(list.toString());
打印数据:
3.Map接口
3.1 forEach
1.源码:
default void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); for (Map.Entry<K, V> entry : entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } action.accept(k, v); } }
2.图解:
3.使用:
Map<String,Integer> map = new HashMap<>(); map.put("zs",1); map.put("ls",2); map.put("ww",3); // 使用匿名内部类 map.forEach(new BiConsumer<String, Integer>() { @Override public void accept(String s, Integer integer) { System.out.println("key:" + s + " val:" + integer); } }); System.out.println("=============="); // 使用lambda表达式 map.forEach((key,val) ->{ System.out.println("key:" + key + " val:" + val); });
打印结果: