jdk1.8 / 函数式接口 /Lambda表达式 /Stream流 笔记

一、Jdk1.8

  接口

     Default 有方法体

            没必要重写

  Static

 函数式接口  有且只有一个抽象方法的接口

              @FunctionInterface

 Stream流

1.在接口中的方法

在jdk1.7中default方法和公开静态方法是不会出现的,jdk1.8之后都可以用

//默认值静态常量
public static final int a=10;

//普通的抽象方法
List<String> test1();

//default方法 一定要方法体
default void test2(){
}

//公开静态方法
public static void test3(){
}

//静态方法在Java中不会被继承或重写。

  1. 函数式接口

函数式接口  有且只有一个抽象方法的接口   @FunctionalInterface

使用@Functionallnterface就只能写一个普通的抽象方法,多写报错!!!

default方法和公开静态方法多个不会报错

3.函数式接口写法

//函数式接口 有且只有一个抽象方法 ()方法参数必须要写
Show show3=() ->{
    System.out.println("33333");
    return null;
};
show3.test1();

4.函数式接口集合写法

//函数式接口集合 第一种写法
Show show4=()->{
    return Arrays.asList("1","2","3");
};
List<String> arrList = show4.test1();
System.out.println(arrList);

//函数式接口简易方法  第二种写法
Show show5=()->Arrays.asList("1","2","3");;
List<String> arrList2 = show4.test1();
System.out.println(arrList2);

  1. 内实现

//内部类 方法1
Show show=new Show() {
    @Override
    public List<String> test1() {
        System.out.println("22222222");
        return null;
    }
};

运行后会添加class文件,下面是如何查看文件步骤:

第一步:

第二步:复制该路径去文件中查找 (\out可以不要)

 第三步:点击target->classes->com

第四步:查看是否有.class文件 (因为没有取名所以默认为1.class文件)

public class Test {
    //内部类 方法2
    class Tt{
        public String name="张明";
    }

}

  查看第四步有Test$Tt.class.文件就说明成功了,因为命名为Tt所以XXTt.class文件

  1. 内实现  非常的常用!!!

//内实现
Show show1=new Showimpl();

  1. 内部类和内实现的区别

 /*内实现/内部类  都是 new这个方法的子类
区别:1.内实现放在其它类只要复制这行照样可以写,多次重复实现
            内部类就要复制全部拿过去,多次重复实现就要全部复制
         2.内实现只能从实现类里面修改
            内部类实现可以直接进行修改*/

  • Lambda表达式

1)是匿名函数

2)基本语法: (Parameters) -> expression或 (Parameters) -> {statements: }

3)Lambda表达式由三部分组成:

  1. Parameters:形参列表,这里的参数是函数式接口里的参数,这里的参数类型可以声明也可不声明。

             另外当只有一个推断类型时可以省略圆括号。

  1. -> :理解为”被用于”的意思
  2. 方法体:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可返回一个值或什么

          都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个或什么都不返回

4)lambda表达式结构  写表达式一定要有return!

1.不需要参数,返回值为 2

   ()->2

  1. 接受一个参数(数字类型),返回值

public interface Show1 {
    //一个参数 int类型
    int test1(int x);
}

//一个参数
Show1 show11=x -> 2*x;  //简写
Show1 show12=x->{  //有方法体
    return 2*x;
};
System.out.println("int类型  一个参数:"+show11.test1(10));
System.out.println("int类型  一个参数:"+show12.test1(10));

  1. 接受2个参数(数字类型),并返回其值

public interface Show2 {
    //两个参数 int类型
    int test2(int x,int y);
}

//两个参数
Show2 show21=(x,y)->{
  return x+y;
};
System.out.println("int类型 两个参数:"+show21.test2(2,3));

  1. 一个参数,无返回值

public interface Show3 {
    //一个参数 无返回
    void  test3(int x);
}

//无返回
Show3 show31 = (x) -> {
    System.out.println("无返回 1个参数: " + x);
};
// 调用lambda表达式
show31.test3(10);

  1. 接受一个String对象, 并在控制台打印,不返回任何值(看起来像是返回void)

(String s)->System.out.print(s)

  • 变量捕获

   //变量捕获
 int a=100;
 Show3 show32=(x)->{
     System.out.println(a);
 };
show32.test3(10);

错误示范:  可以捕获a变量的值进行输出但是不能去修改他的值

//变量捕获
 int a=100;
 Show3 show32=(x)->{
     int a=99;  //错误
     a=99; //错误
     System.out.println(a);
 };
show32.test3(10);

  • Stream流 (实例)

1.创建一个对象 (要有无参/有参构造方法  get/set方法  toString方法)

public class Student implements Serializable{
    private String name;
    private int age;
    private String className;
    private double avg;
    private String address;
    private String sex;
    private String phone;

2.在测试类添加数据

public class StreamTest {
    public static void main(String[] args) {
        List<Student> studentList=new ArrayList<>();
        studentList.add(new Student("小明",18,"一班",98));
        studentList.add(new Student("洪明",17,"二班",98));
        studentList.add(new Student("小药",18,"三班",98));
        studentList.add(new Student("小花",21,"一班",98));
        studentList.add(new Student("黄博",26,"二班",98));
        studentList.add(new Student("李明",12,"三班",98));
        studentList.add(new Student("李明",13,"四班",98));
        studentList.add(new Student("李明",14,"二班",98));
        //添加多条一样的数据
        Student student=new Student("大明",14,"二班",98);
        studentList.add(student);
        studentList.add(student);
        studentList.add(student);

    }
}

3.For循环进行”过滤”操作

List<Student> stuList1 = new ArrayList<>();
for (int i=0;i<studentList.size();i++){
    Student student2=studentList.get(i);
    if(student.getAge()>=20){
        stuList1.add(student2);
    }
}
System.out.println("For循环 进行 ”过滤操作:"+stuList1);

4.Stream流“过滤操作”->stream().filter() 返回boolean类型

//studentList.stream().不能提出来
List<Student> students =
        studentList.stream().filter(stu -> {  //过滤多个条件
            return stu.getAge() >= 20 && stu.getClassName().equals("一班");
   }).collect(Collectors.toList());
System.out.println("Stream  “过滤多个操作1:"+students);

List<Student> students2 =
        studentList.stream().filter(stu -> stu.getAge() >= 20) // 过滤一个条件
                .collect(Collectors.toList());
System.out.println("Stream  “过滤单个操作2:"+students2);

5.”去重“操作 ->stream().distinct()

System.out.println("原长度:"+studentList.size());
List<Student> collect = studentList.stream().distinct().collect(Collectors.toList());
System.out.println("去重后的长度:"+collect.size());

6.”获取前三条数据“操作 ->stream().limit(3)  3可以更改

List<Student> limit = studentList.stream().limit(3).collect(Collectors.toList());
System.out.println("获取前三条数据操作:"+limit);

7.“排序”操作 ->stream().sorted()  比较对象

//第一种排序方式
List<Student> sorted = studentList.stream().sorted((stu1, stu2) -> {
    return stu1.getAge() - stu2.getAge();  //从小到大
}).collect(Collectors.toList());
System.out.println("“排序操作1:"+sorted);

List<Student> sorted2 = studentList.stream().sorted((stu1, stu2) -> {
    return stu2.getAge() - stu1.getAge();  //从大到小
}).collect(Collectors.toList());
System.out.println("“排序操作2:"+sorted2);

//第二种排序方式
List<Student> sorted3 = studentList.stream().sorted().collect(Collectors.toList());
System.out.println("“排序操作2:"+sorted3);

第二种排序方式在实体类中

public class Student implements Serializable,Comparable<Student> {
    private String name;
    private int age;
    private String className;
    private double avg;
    private String address;
    private String sex;
    private String phone;

 @Override
    public int compareTo(Student o) {
        return o.getAge()-this.getAge();
    }
}

8.“任意一条数据”操作  ->stream().anyMatch

  “所有数据”操作  ->stream().allMatch

//返回boolean类型

System.out.println("年龄任意一个大于18:"+studentList.stream().anyMatch(stu->stu.getAge()>18));
System.out.println("年龄全部(所有数据)大于20"+studentList.stream().allMatch(stu->stu.getAge()>20));

9.“获取第一条数据”操作 ->stream().findFirst().get()

Student student1 = studentList.stream().findFirst().get();
System.out.println("获取第一条数据:"+student1);

//按照排序方式获取第一条数据
Student student2 = studentList.stream().sorted().findFirst().get();
System.out.println("按照排序方式获取第一条数据:"+student2);

  1. “从大流里面获取小流 ”操作  -> stream().flatMap

long count = studentList.stream().flatMap(stu -> stu.getScores().stream()).distinct().count(); //去重distinct()及获取总长度count()
System.out.println("“从大流里面获取小流 ”操作:"+count);

在实体类中 (要get/set方法)这是写死了!!

private List<Integer> scores = Arrays.asList(100,98,88,99,45,66,99,78,66,45);

  1. “对象集合转单属性集合”操作 ->stream().map

List<String> maps = studentList.stream().map(stu -> stu.getName()).collect(Collectors.toList());
System.out.println(" “对象集合转单属性集合 ”操作:"+maps);

  1. “在重复中获取第一条/最后一条/拼接数据”操作    

-> stream().collect(Collectors.toMap())

//对象集合 转成  key value
//适合key不重复时使用
//Student::getName ->getName赋值给Student对象

Map<String, Integer> map = studentList.stream().collect(Collectors.toMap(Student::getName, Student::getAge,
        (news, old) -> {
            return news ;
        }));
map.forEach((k,v) -> {
    System.out.println(k + "-" + v);
});

  1. “跳过”操作 ->stream().skip(2) 2可以修改

List<Student> skip = studentList.stream().skip(2).collect(Collectors.toList());
System.out.println("“跳过操作:"+skip);

  1. “偷偷查看”操作 -> stream().peek

studentList.stream().peek(stu->{
    System.out.println("偷偷查看操作 "+stu.getSex());
});

接口的作用是什么

   在面向对象编程中,接口是一种抽象类型,它定义了一组方法的签名(方法名称、参数列表和返回类型),但没有提供这些方法的具体实现。接口只定义了方法的契约,而具体的类需要实现这些方法的具体逻辑。接口的作用主要包括以下几点:

实现多态:接口允许不同的类实现相同的接口,从而实现多态。通过接口,可以定义一组共同的方法,不同的类可以根据自身的需求来实现这些方法,实现了代码的灵活性和扩展性。

实现解耦:接口可以帮助实现解耦,即降低类之间的耦合度。当一个类依赖于接口而不是具体的类时,可以更容易地替换实际的实现类,从而降低代码的依赖性。

定义规范:接口定义了一组方法的规范,使得类在实现接口时必须提供这些方法的具体实现。这有助于提高代码的可读性和可维护性,同时也有利于团队协作。

实现多继承:Java 中类只支持单继承,但是一个类可以实现多个接口。通过接口,一个类可以获得多个接口的特性,实现了类的多继承。

实现回调:接口可以用于实现回调机制,即一个对象通过接口调用另一个对象的方法。这种方式可以实现事件处理、监听器等功能。

总的来说,接口在面向对象编程中扮演着重要的角色,它提供了一种抽象机制,使得代码更加灵活、可扩展和易于维护。通过接口,可以定义一组方法的规范,实现多态、解耦和规范化代码的编写。

default的好处是什么

 在Java 8中引入了接口的默认方法(default method),这使得接口可以包含具有默认实现的方法。默认方法在接口中定义,可以被实现接口的所有类继承或覆盖,也可以被类直接调用。默认方法的好处包括:

向后兼容性:引入默认方法后,可以在不破坏现有代码的情况下向接口中添加新的方法。这使得接口的演变变得更加容易,同时保持了现有代码的向后兼容性。

接口的扩展性:默认方法使得接口可以包含方法的默认实现,从而减少了实现类需要实现的方法数量。这样,接口可以在不影响现有实现类的情况下,向接口中添加新的方法。

代码复用:默认方法提供了一种在接口中实现通用逻辑的方式,这样实现类可以直接继承默认方法的实现,避免了重复编写相同的代码。

接口的演化:默认方法使得接口可以逐渐演化,向现有接口中添加新的方法而不需要修改所有实现该接口的类。这有助于在不破坏现有代码的情况下对接口进行修改和扩展。

提供了一种新的设计模式:默认方法的引入为新的设计模式提供了可能性,例如接口的扩展、接口的组合等,使得代码结构更加灵活和易于维护。

总的来说,默认方法为Java接口带来了更大的灵活性和功能性,使得接口可以更好地适应需求的变化,同时提高了代码的复用性和可维护性。

  • 27
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值