【Java进阶】Java基础知识点之集合进阶用法(lambda、方法引用等详解)

一、可变参数

1、介绍

  • JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以使用可变参数对其简化。可变参数底层其实就是一个数组,好处是在传递数据的时候,省的我们自己创建数组并添加元素,JDK底层帮我们自动创建数组并添加元素了。

2、格式

    //格式: 修饰符  返回值类型 方法名(参数类型... 形参名){  }
    public static  int getSum(int ... args) {
        int result = 0;
        for (int agr: args) {
            result = result + agr;
        }
        return result;
    }
    //使用
    System.out.println(getSum(10, 18, 30, 55));    

3、注意点

  • 一个方法只能有一个可变参数;
  • 如果方法中有多个参数,可变参数要放到最后。

4、应用场景

  • Collections类中实现添加元素的一些方法,使用了可变参数。
    //Collections addAll方法源码
    public static <T> boolean addAll(Collection<? super T> c, T... elements) {
        boolean result = false;
        for (T element : elements)
            result |= c.add(element);
        return result;
    }
    //addAll使用
    public static void main(String[] args) {
      ArrayList<Integer> list = new ArrayList<Integer>();
      //原来写法
      //list.add(12);
      //list.add(14);
      //list.add(15);
      //list.add(1000);
      
      //采用工具类 完成 往集合中添加元素  
      Collections.addAll(list, 5, 222, 12);
      System.out.println(list);
    }
  • Stream类中的静态方法 of 方法
    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    }

二、Collections工具类

1、介绍

  • java.utils.Collections是集合工具类,用来对集合进行操作。

2、常用方法

  • public static void shuffle(List<?> list) : 打乱集合顺序。
  • public static <T> void sort(List<T> list): 将集合中元素按照默认规则排序。
  • public static <T> void sort(List<T> list,Comparator<? super T> ): 将集合中元素按照指定规则排序。

3、Comparator比较器

        ArrayList<Student> list = new ArrayList<Student>();

        list.add(new Student("rose",18));
        list.add(new Student("jack",16));
        list.add(new Student("abc",20));

        //实现Comparator比较器,使用自定义排序
		Collections.sort(list, new Comparator<Student>() {
  		  @Override
    		public int compare(Student o1, Student o2) {
        	return o1.getAge()-o2.getAge();//以学生的年龄升序
   		 }
		});

三、Lambda表达式

1、介绍

Lambda表达式,也可称为闭包,是Java 8中引入的一个新特性。一个lambda表达式是一个匿名函数,并且这个函数没有名称且不属于任何类。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

2、语法

	(parameters) -> expression
	或
	(parameters) ->{ statements; }
  • 以下是lambda表达式的重要特征:
    • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
    • 可选的参数圆括号:只有一个参数时,无需定义圆括号;但多个参数需要定义圆括号。
    • 可选的大括号:如果主体只包含了一个语句,就不需要使用大括号
    • 可选的返回关键字:如果主体只有一个表达式返回值,则编译器会自动返回值,大括号需 要指定表达式返回了一个数值。

3、表达式例子

```java
	// 1. 不需要参数,返回值为 5  
	() -> 5  
	  
	// 2. 接收一个参数(数字类型),返回其2倍的值  
	x -> 2 * x  
	  
	// 3. 接受2个参数(数字),并返回他们的差值  
	(x, y) -> x – y  
	  
	// 4. 接收2个int型整数,返回他们的和  
	(int x, int y) -> x + y  
	  
	// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
	(String s) -> System.out.print(s)
```

3、使用Lambda表达式

  • 要使用lambda表达式,需要建立本身的功能接口或使用Java提供的预定义功能接口。
  • 功能性接口(或单一抽象方法接口),又称函数式接口,指的是有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式。例如:可运行接口、可调用接口、动作监听者等等。
public class LambdaTest {

    //定义功能接口
    @FunctionalInterface
    interface MathOperation {
        int operation(int a, int b);
    }

    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }

    public static void main(String[] args) {

        //不声明类型
        MathOperation add = (x, y) -> x + y;

        //声明类型
        MathOperation sub = (int x, int y) -> x - y;

        // 大括号中的返回语句
        MathOperation multiplication = (int a, int b) -> { return a * b; };

        // 没有大括号及返回语句
        MathOperation division = (int a, int b) -> a / b;

        //函数作为参数
        LambdaTest test = new LambdaTest();
        test.operate(10, 15, (x, y)-> x + y);

        //lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
        /*
        int var = 100;
        MathOperation error = (x, y) -> {
            var = x + 100; //error: Variable used in lambda expression should be final or effectively final
           return x - y;
        };
        */
    }
}

4、变量作用域

  • lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
  • lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
  • Lambda 表达式中可以直接访问外层的局部变量;
  • 在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

5、函数式接口

  • 介绍
    函数式接口,指的是有且仅有一个抽象方法,但是可以有多个非抽象方法的接口;又称功能性接口或单一抽象方法接口
  • 不能使用以下类型的方法来声明一个函数式接口:
    • default方法
    • 静态方法
    • 从Object类继承的方法(如:Comparator接口中的equals()方法)
  • 案例说明
    /*一个函数式接口可以重新声明Object类中的方法。该方法不被视为抽象方法。
      Comparator接口有两个抽象方法:compare()和equals()。
      equals()方法是Object类中的equals()方法的重新声明。
    */
    @FunctionalInterface
    public interface Comparator<T> {
    	int compare(T o1, T o2);
    	boolean equals(Object obj);
    }
    

6、注解 @FunctionalInterface

  • @FunctionalInterface该注解主要是:一种信息性注释类型,用于指示接口类型声明是Java语言规范中定义的函数式接口(功能接口)。
  • 如果接口上只有一个抽象方法,但我们没有对其加上@FunctionalInterface 编译器仍然将其看作函数式接口。该注解是给编译器做检查使用的,如果使用了该注解,编译器就会检查该接口中的抽象方法是不是只有一个,如果有多个就会报错。

7、四大内置函数式接口

  • 消费型接口: Consumer< T>; void accept(T t) 有参数,无返回值的抽象方法;
    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
    }
    
  • 供给型接口: Supplier < T>; T get() 无参有返回值的抽象方法;
    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }
    
  • 断定型接口: Predicate; boolean test(T t):有参,但是返回值类型是固定的boolean;
    @FunctionalInterface
    public interface Predicate<T> {
         boolean test(T t);
    }
    
  • 函数型接口: Function<T,R> ;R apply(T t)有参有返回值的抽象方法;
    @FunctionalInterface
    public interface Function<T, R> {
         R apply(T t);
    }
    
  • 示例
       //消费型接口: Consumer< T> void accept(T t)有参数,无返回值的抽象方法;
       Consumer<String> consumer = (x)->System.out.println(x);
       consumer.accept("Consumer");
    
       //供给型接口: Supplier < T> T get() 无参有返回值的抽象方法;
       Supplier<String> supplier = ()->{ return "Supplier";};
       System.out.println(supplier.get());
    
       //断定型接口: Predicate<T> boolean test(T t):有参,但是返回值类型是固定的boolean;
       Predicate<String> predicate = (x)->x == null;
       System.out.println(predicate.test("abc"));
    
       //函数型接口: Function<T,R> R apply(T t)有参有返回值的抽象方法;
       Function<String, String> function = (x)->{return x + "-" + "bbb";};
       System.out.println(function.apply("function"));
    

四、不可变集合

1、什么是不可变集合

是一个长度不可变,内容也无法修改的集合

2、使用场景

如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。当集合对象被不可信的库调用时,不可变形式是安全的。

3、不可变集合的分类

3.1、不可变的list集合

  /**
   * 1. 创建不可变list集合
   */
  List<String> stockCode = List.of("SH6000000", "SH6000001", "SH6000002", "SH6000003");

  /** error: java.lang.UnsupportedOperationException
  stockCode.add("SH3000000");
  stockCode.set(0, "SH3000000");
  stockCode.remove("SH3000000");
   */

3.2、不可变的set集合

  /**
   * 1. 创建不可变set集合(获取一个不可变的Set集合时,参数一定要保证唯一性,不可重复)
   */
  Set<String> stockCode = Set.of("SH6000000", "SH6000001", "SH6000002", "SH6000003");
  
  /** error: java.lang.UnsupportedOperationException
   stockCode.add("SH3000000");
   stockCode.remove("SH3000000");
   */

3.2 不可变的map集合

    /**
     * 1. 创建键值对不超过10个的不可变Map集合
     */
    Map.of("SH6000000", "9.90", "SH6000001", "19.90", "SH6000002", "29.90");

    /**
     * 2. 创建键值对超过10个的不可变Map集合
     */
    Map<String, String> hm = new HashMap<>();
    hm.put("张三", "南京");
    hm.put("李四", "北京");
    hm.put("王五", "上海");
    hm.put("赵六", "北京");
    hm.put("孙七", "深圳");
    hm.put("周八", "杭州");
    hm.put("吴九", "宁波");
    hm.put("郑十", "苏州");
    hm.put("刘一", "无锡");
    hm.put("陈二", "嘉兴");
    hm.put("aaa", "111");

    //方法1:
    Set<Map.Entry<String, String>> entries = hm.entrySet();
    Map.Entry[] arr =  entries.toArray(new Map.Entry[0]);
    Map immutableMap1 = Map.ofEntries(arr);

    //可简化为如下写法:
    Map immutableMap2 = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));

    /**
     *  toArray 方法在底层会比较集合的长度跟数组的长度两者的大小
     *  如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用;
     *  如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组; 因此new Map.Entry[0] 直接指定长度为0即可,不用指定实际长度。
     */

    /**
     * 方法2:使用copyOf, jdk10或以上版本可用
     * copyOf实现
     *     static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {
     *         if (map instanceof ImmutableCollections.AbstractImmutableMap) {
     *             return (Map<K,V>)map;
     *         } else {
     *             return (Map<K,V>)Map.ofEntries(map.entrySet().toArray(new Entry[0]));
     *         }
     *     }
     */
    Map<String, String> immutableMap3 = Map.copyOf(hm);

五、Stream流

1、介绍

  • 概念
  • Stream流的思想
  • Stream流的三类方法
    • 获取Stream流
      • 创建一条流水线,并把数据放到流水线上准备进行操作
    • 中间方法
      • 流水线上的操作
      • 一次操作完毕之后, 还可以继续进行其他操作
    • 终结方法
      • 一个Stream流只能有一个终结方法
      • 是流水线上的最后一个操作

2、常见生成Stream流的方式

  • Collection体系集合
    使用默认方法stream()生成流, default Stream stream()
  • Map体系集合
    把Map转成Set集合,间接的生成流
  • 数组
    通过Arrays中的静态方法stream生成流
  • 同种数据类型的多个数据
    通过Stream接口的静态方法of(T… values)生成流
    /*1. 生成方式*/
    //Collection体系:使用默认方法stream()生成流
    List<String> lst = new ArrayList<>();
    Stream<String> lstStream = lst.stream();

    Set<String> set = new HashSet<>();
    Stream<String> setStream = set.stream();

    //Map体系:把Map转成Set集合,间接的生成流
    Map<String, String> map = new HashMap<>();
    Stream<String> valStream = map.values().stream();
    Stream<String> keyStream = map.keySet().stream();
    Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();

    //数组:通过Arrays中的静态方法stream生成流
    String[] array = {"hello", "world", "test1"};
    Stream<String> arrStream = Arrays.stream(array);

    //同种数据类型的多个数据:通过Stream接口的静态方法of(T... values)生成流
    Stream<String> strArrStream = Stream.of("hello", "world", "test1");
    Stream<Integer> intArrStream = Stream.of(1, 2, 3);

3、Stream流的中间操作方法

  • 概念
    • 中间操作的意思是, 执行完此方法之后, Stream流依然可以继续执行其他操作
  • 常见方法
方法名说明
Stream filter(Predicate predicate)用于对流中的数据进行过滤
Stream limit(long maxSize)返回此流中的元素组成的流,截取前指定参数个数的数据
Stream skip(long n)跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static Stream concat(Stream a, Stream b)合并a和b两个流为一个流
Stream distinct()返回由该流的不同元素(根据Object.equals(Object) )组成的流
Stream map(Function<? super T, ? extends R> mapper)对流中的每个元素应用一个函数,将其映射为新的元素
	 /*2. 中间操作方法*/
	 //filter
	 List<String> lst1 = new LinkedList<>();
	 lst1.add("SZ.300000");
	 lst1.add("SZ.300001");
	 lst1.add("SZ.300002");
	 lst1.add("SH.600000");
	 lst1.add("SH.600001");
	 lst1.add("SH.600002");
	
	 //a. 重写Predicate中的test方法进行filter
	 // idea提示:Anonymous new Predicate<String>() can be replaced with lambda
	 lst1.stream().filter(new Predicate<String>() {
	     @Override
	     public boolean test(String s) {
	         return s.startsWith("SH");
	     }
	 }).forEach(x->System.out.println(x));
	 System.out.println("--------");
	
	 //b. 因为Predicate接口中只有一个抽象方法test,可以使用lambda表达式来简化
	 lst1.stream().filter((String x)-> { return x.startsWith("SH"); }).forEach(x->System.out.println(x));
	 System.out.println("--------");
	
	 //c. 进一步简化lambda
	 lst1.stream().filter(x->x.startsWith("SH")).forEach(x->System.out.println(x));
	 System.out.println("--------");
	
	 //limit && skip
	 //取前3个数据在控制台输出
	 lst1.stream().limit(3).forEach(x->System.out.println(x));
	 System.out.println("--------");
	
	 //跳过2个元素,把剩下的元素中前2个在控制台输出
	 lst1.stream().skip(2).limit(2).forEach(x->System.out.println(x));
	 System.out.println("--------");
	
	 //concat && distinct
	 Stream<String> stream1 = lst1.stream().limit(4);
	 Stream<String> stream2 = lst1.stream().skip(2);
	
	 //合并stream1和stream2得到的流,并把结果在控制台输出,要求字符串元素不能重复
	 Stream.concat(stream1, stream2).distinct().forEach(x->System.out.println(x));

4、Stream流的终结操作方法

  • 概念
    • 终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作
  • 常用方法
方法名说明
void forEach(Consumer action)对此流的每个元素执行操作
long count()返回此流中的元素数

5、Stream流的收集操作

  • 概念
    • 对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中
  • 常用方法
方法名说明
R collect(Collector collector)把结果收集到集合中
  • 工具类Collectors 提供了具体的收集方式
方法名说明
public static Collector toList()把元素收集到List集合中
public static Collector toSet()把元素收集到Set集合中
public static Collector toMap(Function keyMapper, Function valueMapper)把元素收集到Map集合中
   /*3. collect*/
   //处理过程:
   //1.filter负责过滤数据的.
   //2.collect负责收集数据; 获取流中剩余的数据, 但是他不负责创建容器, 也不负责把数据添加到容器中.
   //3.Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.
   Set<String>  set1 = lst1.stream().filter(x->x.startsWith("SZ")).collect(Collectors.toSet());
   System.out.println(set1);

    //toMap
     // collect方法只能获取到流中剩余的每一个数据.
	//在底层不能创建容器,也不能把数据添加到容器当中
	//Collectors.toMap 创建一个map集合并将数据添加到集合当中	
	// s 依次表示流中的每一个数据	
	ArrayList<String> list = new ArrayList<>();
	list.add("zhangsan,23");
	list.add("lisi,24");
	list.add("wangwu,25");
	
	Map<String, Integer> map = list.stream().filter(
	       s -> {
	           String[] split = s.split(",");
	           int age = Integer.parseInt(split[1]);
	           return age >= 24;
	       }
	).collect(Collectors.toMap(
		 //第一个lambda表达式就是如何获取到Map中的键
	     //第二个lambda表达式就是如何获取Map中的值
	       s -> s.split(",")[0],
	       s -> Integer.parseInt(s.split(",")[1]) ));
	
	System.out.println(map);

六、方法引用

1、介绍

  • 概述
    方法引用就是指直接使用已经存在的方法,当作函数式接口中抽象方法的方法体。(函数式接口就类似于C里的函数指针,而方法引用就是函数指针指向的具体函数实现
  • 使用要求
    • 1.需要有函数式接口(FunctionalInterface)
    • 2.被引用的方法必须已经存在
    • 3.被引用方法的形参和返回值需要跟抽象方法保持一致
    • 4.被引用方法的功能要满足当前需求
  • 方法引用符
    :: 该符号为引用运算符,而它所在的表达式被称为方法引用
  • 案例说明
    public class FunctionDemo {
        public static void main(String[] args) {
            //需求:创建一个数组,进行倒序排列
            Integer[] arr = {3, 5, 4, 1, 6, 2};
    
            /**
             * 实现要点,使用数字自带的Arrays.sort方法进行排序
             *  public static <T> void sort(T[] a, Comparator<? super T> c) {
             *  }
             */
    
            /**
             * 实现方式
             */
            //1. 匿名内部类
            Arrays.sort(arr, new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2 - o1;
                }
            });
            System.out.println(Arrays.toString(arr));
    
            //2.lambda表达式
            Arrays.sort(arr, (Integer o1, Integer o2) -> {return o2 - o1;});
            System.out.println(Arrays.toString(arr));
    
            //3.简化lambda表达式
            Arrays.sort(arr, (o1, o2) ->  o2 - o1);
            System.out.println(Arrays.toString(arr));
    
            /**4.方法引用
             * - 需要有函数式接口(FunctionalInterface)
             * - 被引用的方法必须已经存在
             * - 被引用方法的形参和返回值需要跟抽象方法保持一致
             * - 被引用方法的功能要满足当前需求
             */
            Arrays.sort(arr, FunctionDemo::compareTo);
            System.out.println(Arrays.toString(arr));
        }
        public static Integer compareTo(Integer o1, Integer o2) {
            return o2 - o1;
        }
    }	
    

2、方法引用的分类

  • 2.1 引用静态方法

    • 格式
      类名::静态方法
    • 范例
      Integer::parseInt
    • 案例说明
         /*
          需求:
              集合中有以下数字,要求把他们都变成int类型
              "1","2","3","4","5"
         */
      
          ArrayList<String> list = new ArrayList<>();
          Collections.addAll(list, "1","2","3","4","5");
      
          //1.使用匿名内部类
          list.stream().map(new Function<String, Integer>() {
              @Override
              public Integer apply(String x) {
                  return Integer.parseInt(x);
              }
          }).forEach(x->System.out.println(x));
      
          /* 2.使用方法引用(引用静态方法)
           * public static int parseInt(String s)
           */
          list.stream().map(Integer::parseInt).forEach(x->System.out.println(x));    
      
  • 2.2 引用成员方法

    引用其他类的成员方法引用本类的成员方法引用父类的成员方法
    格式其他类对象::方法名this::方法名super::方法名
    范例FunctionDemo demo = new FunctionDemo; demo::FunctionDemo; ==> new FunctionDemo::operatorFuncthis::operatorFuncsuper::operatorFunc
    注意事项类的静态方法是没有this的,如果要在静态方法中使用引用本类的成员方法,需要创建本类的对象类的静态方法是没有super的,如果要在静态方法中使用引用本类的成员方法,需要创建本类的对象
  • 2.3 引用构造方法

    • 格式
      类名::new
    • 目的
      创建这个类的对象
    • 范例
      //Collectors.toList()方法的实现就是通过引用构造方法的形式进行对象创建
      Collector<T, ?, List<T>> toList() {
          return new CollectorImpl<>(ArrayList::new, List::add,
                                     (left, right) -> { left.addAll(right); return left; },
                                     CH_ID);
      }
      
      //说明:CollectorImpl类中的构造方法第一个参数是Supplier<A>,而Supplier<A>是一个函数式接口,它的抽象方法是没有参数,返回一个泛型类型A对象,而构造函数恰恰就是返回一个对象的。
      CollectorImpl(Supplier<A> supplier,
                        BiConsumer<A, T> accumulator,
                        BinaryOperator<A> combiner,
                        Set<Characteristics> characteristics);
                        
      @FunctionalInterface
      public interface Supplier<T> {	
          /**
           * Gets a result.
           *
           * @return a result
           */
          T get();
      }                      
      
  • 2.4 其他调用方式

    • 使用类名引用成员方法
      • 格式
        类名::成员方法
      • 范例
        String::toUpperCase
      • 使用要求
        • 需要有函数式接口
        • 被引用的方法必须已经存在
        • 被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致
          • 抽象方法形参的详解:
            • 第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法。例如:在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是String类型,那么使用这种方式进行方法引用,只能引用String这个类中的方法
            • 第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法。
            • 代码示例
                    //1.创建集合对象
                    ArrayList<String> list = new ArrayList<>();
                    //2.添加数据
                    Collections.addAll(list, "aaa", "bbb", "ccc", "ddd");
                    //3.变成大写后进行输出
                    //拿着流里面的每一个数据,去调用String类中的toUpperCase方法,方法的返回值就是转换之后的结果。
                    /**
                     * 1. toUpperCase函数定义:public String toUpperCase();
                     * 2. map的抽象函数定义:public interface Function<T, R> { R apply(T t);}
                     * 3. 抽象方法中的第一个参数T类型对应流中的String类型,则引用处只能使用String类的成员方法;抽象方法没有第二个参数,并且 String::toUpperCase为无参的成员方法,因此可以使用类的成员方法作为引用
                    */
                    list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));
              
        • 被引用方法的功能需要满足当前的需求
      • 局限性
        • 不能引用所有类中的成员方法。具体可以引用的类,跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。
    • 引用数组的构造方法
      • 格式
        数据类型[]::new
      • 范例
        int[]::new
      • 目的
        创建数组
      • 注意事项
        数组的类型需要与流中的数据类型保持一致
      • 代码示例
                //1.创建集合并添加元素
              ArrayList<Integer> list = new ArrayList<>();
              Collections.addAll(list, 1, 2, 3, 4, 5);
              
              //2.收集到数组当中
              /*Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
                  @Override
                  public Integer[] apply(int value) {
                      return new Integer[value];
                  }
              });*/
             Integer[] arr2 = list.stream().toArray(Integer[]::new);
        

3、方法引用使用技巧

  • 思考有没有满足需求的现有方法;
  • 如果存在这样的方法,则思考该方法是否满足方法引用的规则,是否满足哪类方法引用。
    • 引用静态方法
    • 引用成员方法
    • 引用构造方法

4、匿名内部类、Lambda表达式、方法引用比较

  • 4.1、匿名内部类可进化为方法引用;
  • 4.2、匿名内部类可进化为lambda;
  • 4.3、lambda可进化为方法引用;
  • 4.4、方法引用为最简洁的写法,其次lambda,最后是匿名内部类。
  • 4.5、方法引用常见搭配流使用,尤其流处理中使用map进行映射处理时,适合使用方法引用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值