jdk都出到16了8还没掌握吗?挽周带你玩转java8新特性(建议收藏)(二)

简介: jdk都出到16了8还没掌握吗?挽周带你玩转java8新特性(建议收藏)

三.方法引用与构造器引用

方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用 ! 方法引用可以看作是Lambda表达式深层次的表达,换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

语法:

使用操作符 “::” 将类(或对象)与方法名分割开来。

要求:实现接口的抽象方法的参数和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!

案例:

  1. 格式:对象 : : 非静态方法
    @Test
    public void test(){
        //Lambda表达式写法
        Consumer<String> consumer = str ->System.out.println(str);
        consumer.accept("Lambda表达式");
        //方法引用写法
        Consumer<String> fConsumer = System.out::println;
        fConsumer.accept("方法引用");
    }

20210606231044843.png

  1. 格式:类 : : 静态方法
public class LambdaTest {
    @Test
    public void test(){
        //Lambda表达式写法 比较两个数大小
        Comparator<Integer> comparator =(t1,t2) -> Integer.compare(t1,t2);
        System.out.println(comparator.compare(10,20));
        //方法引用写法
        Comparator<Integer> fComparator = Integer::compare;
        System.out.println(fComparator.compare(20,10));
    }
}

20210606232934127.png

格式:类 : : 非静态方法

20210606234025301.png

20210606234045562.png

public class LambdaTest {
    @Test
    public void test(){
        //Lambda表达式写法
       Comparator<String> comparator=(s1,s2) -> s1.compareTo(s2);
       System.out.println(comparator.compare("abc","abd"));
        //方法引用写法
        Comparator<String> fComparator = String::compareTo;
        System.out.println(fComparator.compare("www","www"));
    }
}

20210606233710864.png

正常来说comparator.compare("abc","abd")有两个参数,而s1.compareTo(s2)只有一个参数并不满足上述所说的方法引用的要求。但是为什么能用呢?因为这种情况下,第一个参数作为方法的调用者出现((s1,s2) -> s1.compareTo(s2)),这种情况下也存在方法引用。只不过这时候我们不是拿具体的对象写,而是拿它的类写(Comparator<String> fComparator = String::compareTo;)

构造器引用

调用的构造器会根据实现的函数接口的抽象方法的参数列表来确定,如果抽象方法为无参的,则调用的构造器也是无参的。

语法:

ClassName :: new

案例

public class Student {
  public Student() {
    System.out.println("Student 无参构造已执行");
  }
  public Student(Integer id) {
    System.out.println("Student 有参构造,一个参数.为:"+id);
  }
  public Student(Integer id, String name, char sex) {
    this.id = id;
    this.name = name;
    this.sex = sex;
  }
  private Integer id;
  private String name;
  private char sex;
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public char getsex() {
    return sex;
  }
  public void setsex(char sex) {
    this.sex = sex;
  }
  @Override
  public String toString() {
    return "Student{" +
        "id=" + id +
        ", name='" + name + '\'' +
        ", sex=" + sex +
        '}';
  }
}
  1. 通过无参构造器引用(创建对象)
public class LambdaTest {
  @Test
  public void test(){
    //原始写法
    Supplier<Student> supplier =new Supplier<Student>() {
      @Override
      public Student get() {
        return new Student();
      }
    };
    supplier.get();
    //lambda表达式写法
    Supplier<Student> lSupplier =()-> new Student();
    lSupplier.get();
    //构造器引用写法
    Supplier<Student> gSupplier = Student::new;
    gSupplier.get();
  }
}

20210607091609642.png

  1. 通过有参构造器引用(一个参数,创建对象)
  @Test
  public void test(){
    //原始写法
    Function<Integer,Student> function =new Function<Integer, Student>() {
      @Override
      public Student apply(Integer integer) {
        return new Student(integer);
      }
    };
    function.apply(1);
    //lambda表达式写法
    Function<Integer,Student> lFunction = id -> new Student(id);
    lFunction.apply(2);
    //构造器引用写法
    Function<Integer,Student> gFunction = Student::new;
    gFunction.apply(3);
  }

20210607093641202.png

数组引用

大家可以把数组看做是一个特殊的类,写法与构造器引用一致。

public class LambdaTest {
  @Test
  public void test(){
    //原始写法
    Function<Integer,String[]> function =new Function<Integer, String[]>() {
      @Override
      public String[] apply(Integer integer) {
        return new String[integer];
      }
    };
    System.out.println(Arrays.toString(function.apply(10)));
    //lambda表达式写法
    Function<Integer,String[]> lFunction= length -> new String[length];
    System.out.println(Arrays.toString(lFunction.apply(20)));
    //构造器引用写法
    Function<Integer,String[]> gFunction = String[] :: new;
    System.out.println(Arrays.toString(gFunction.apply(30)));
  }
}

20210607100532800.png

四.Stream API


Java8中有两大最为重要的改变。第一个是Lambda表达式;另外一个则是Stream API。

Stream API(java.util.Stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API 可以极大提供Java程序员的生产力,让程序员写出高效率,干净,简洁的代码。


(Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。)


Strema到底是什么呢?

是数据渠道,用于操作数据源(集合,数组等) 所生成的元素序列。

“集合将的是数据,Stream讲的是计算!”

语法

集合或数组.stream().过滤().映射().终止操作


Stream 操作的三个步骤

  1. 创建 Stream
    一个数据源(集合,数组),获取一个流
  2. 中间操作
    一个中间操作链,对数据源的数据进行处理
  3. 终止操作(终端操作)
    一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用

image.png

注意:

  1. Stream 自已不会存储元素
  2. Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
  3. Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

案例(围绕以上三点进行操作)

首先我们先来了解两个概念

并行流(parallelStream):多个线程同时运行

顺序流(stream):使用主线程,单线程

  • Stream 实例化
  • 创建 Stream 方式一:通过集合创建
public class LambdaTest {
  @Test
  public void test(){
    List<Student> students= StudentData.getStudent();
    //返回一个顺序流
    Stream<Student> stream = students.stream();
    //返回一个并行流
    Stream<Student> parallelStream = students.parallelStream();
  }
}

创建 Stream 方式二:通过数组创建(Java8中的Arrays的静态方法 Stream()可以获取数组流)

public class LambdaTest {
  @Test
  public void test(){
    int[] arr =new int[]{1,2,3,4,5};
    //通过泛型识明你的类型 放进去的是一个int类型的数组,返回的也是int类型的流
    IntStream stream = Arrays.stream(arr);
  }
}

创建 Stream 方式三:通过Stream的of()

public class LambdaTest {
  @Test
  public void test(){
    Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
  }
}

创建 Stream方式四:创建无限流 (了解)

public class LambdaTest {
  @Test
  public void test(){
    /**
     * 例子:遍历前10个偶数并打印出来
     * iterate(): 迭代
     * seed:种子
     * UnaryOperator:函数式接口
     * 注意:无限流不加对应的中间操作会无限的进行迭代 limit(10):前10个
     */
    Stream.iterate(0, t -> t+2).limit(10).forEach(System.out::println);
  }
}
相关文章
|
3天前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
14 3
|
7天前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
32 1
|
1天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
9 3
|
4天前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
19 6
|
1天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
7 2
|
1天前
|
Java 开发者
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素。通过哈希表和红黑树两种模式,Set能够高效地识别并拒绝重复元素的入侵,确保集合的纯净。无论是HashSet还是TreeSet,都能在不同的场景下发挥出色的表现,成为开发者手中的利器。
11 2
|
1天前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
9 2
|
3天前
|
存储 Java 数据处理
在Java集合框架中,Set接口以其独特的“不重复”特性脱颖而出
【10月更文挑战第14天】在Java集合框架中,Set接口以其独特的“不重复”特性脱颖而出。本文通过两个案例展示了Set的实用性和高效性:快速去重和高效查找。通过将列表转换为HashSet,可以轻松实现去重;而Set的contains方法则提供了快速的元素查找功能。这些特性使Set成为处理大量数据时的利器。
12 4
|
4天前
|
存储 Java 数据处理
Java中的Set接口以其独特的“不重复”特性,在集合框架中占据重要地位。
【10月更文挑战第13天】Java中的Set接口以其独特的“不重复”特性,在集合框架中占据重要地位。本文通过两个案例展示了Set的实用性和高效性:快速去重和高效查找。通过将列表转换为HashSet,可以轻松实现去重;而Set的contains方法则提供了高效的元素查找功能。这些特性使Set在处理大量数据时表现出色,值得我们在日常编程中充分利用。
18 3
|
7天前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
72 0