Lambda方法引用&Stream流&单元测试&单例模式

总结

  • 回顾接口

    可存放:

    ​ 常量
    ​ 抽象方法
    ​ default方法
    ​ static方法

匿名内部类:接口和抽象类对象只使用一次,就可以使用匿名内部类

当使用匿名内部类创建一个函数式接口的时候,可以使用lambda来简化匿名内部类

public class ReviewLambdaDemo {
    public static void main(String[] args) {
        // 1、通过Runnable接口来创建线程对象
         new Thread(() -> System.out.println("2023要结束了")).start();

         // 2、在一个list集合里面放入5个数字,将按数字的降序排列
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,60,3,12,56);
        TreeSet<Integer> ts = new TreeSet<>((a,b) -> b - a);
        ts.addAll(list);
        System.out.println(ts);

        // 3、将一个指定文件夹里面所有ppt文件拿到
        File file = new File("e:/pp");
        File[] files = file.listFiles(f -> f.isFile() && f.getName().endsWith(".ppt"));
        // 遍历数组
        for (File f : files) {
            System.out.println(f);
        }

        // 4、随机产生10个不重复的随机偶数,遍历
        HashSet<Integer> set = new HashSet<>();
        while (set.size() < 10) {
            int num = (int)(Math.random() * 20 + 1);
            if(num % 2 != 0) continue;
            set.add(num);
        }
        set.forEach(a -> System.out.println(a));
    }

}

Lambda

  • 语法结构 简化使用匿名内部类创建对象的

  • 方法引用:简化特殊lambda

    构造方法引用:类名::new
    实例的方法的引用:对象名::方法名
    类方法的方法引用:类名::方法名

  • 讲解方法引用
    方法引用:对特殊的lambda简化的一种语法
    ()-> {lambda体}
    特殊的lambda:当lambda体只有1句代码,并且这句代码是在调用一个方法
    java中的方法:
    构造方法:new 构造方法()
    实例方法:对象名.方法名()
    类方法(静态方法):类名.方法名()

    构造方法的方法引用的语法:类名::方法名(简化lambda调用构造方法)

public class LambdaDemo1 {
    public static void main(String[] args) {
       // 创建IFacotryDog对象
        IFacotryDog ifd = (name,age) -> new Dog(name,age); // 创建函数接口对象
        Dog d = ifd.create("小可爱", 3);
        System.out.println(d);

        // 上面代码中lambda,可以使用构造方法的引用来简化
        // 创建IFacotryDog对象
        IFacotryDog ifd2 = Dog::new; // 类名:调用构造方法的类名::new
        Dog d2 = ifd2.create("老可爱", 3);
        System.out.println(d2);


    }
}
public class Dog {
    private String name;
    private Integer age;

    public Dog() {
    }

    public Dog(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
/**
 * 创建Dog对象的接口
 */
public interface IFacotryDog {
    Dog create(String name,Integer age);
}

类方法引用:类名(调用方法存放的类)::方法名(要调用的方法名)

public interface IChangeStringNumber {
    int change(String number);
}

/**
 * 讲解类方法引用:类名(调用方法存放的类)::方法名(要调用的方法名)
 */
public class LambdaDemo2 {
    public static void main(String[] args) {
        // 创建函数式接口IChangeStringNumber对象
        IChangeStringNumber  icsn = n -> Integer.parseInt(n);
        int num = icsn.change("123");
        System.out.println(num);
        
        // 上面代码中lambda是在调用一个类方法,使用类方法引用来简化:类名::方法
        
        IChangeStringNumber icsn2 = Integer::parseInt;
        icsn2.change("123");

    }
}

实例方法的引用:对象::实例方法名

/**
 * 设计一个函数式接口
 */
public interface IIsAvi {
    boolean isAvi(String filename);

}
/**
 * 讲解实例方法的引用
 */
public class LmbdaDemo3 {
    public static void main(String[] args) {

        // 创建IIsAvi对象
        IIsAvi avi = fn -> fn.endsWith(".avi"); // 创建函数式接口的对象
        boolean temp = avi.isAvi("蘋蘋在某酒店学习外语.png");
        System.out.println(temp);

        // lambda在调用一个实例方法,用实例方法引用来简化:对象::方法名

        String f = "xxxx.txt";
        IIsAvi avi2 = f::endsWith; // 实例方法的引用
        boolean avi1 = avi2.isAvi(f);
        System.out.println(avi1);

        // 遍历集合
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
//        PrintStream ps = System.out;
//        list.forEach(a -> ps.println(a));
        list.forEach(System.out::println);

    }
}

特殊:类名.方法名()

​ 引用类的实例方法是一种引用特定对象的实例方法。它通常用于将对象的方法作为Lambda表达式的一部分引用。

注意:仅限于对象的get()或)set()方法

stream.map(Person::getName); // 把对象转为对象的name

Stream流

IO流是操作文件流
Stream操作数组或者集合的流
注意:Stream只操作数据,不保存数据

  • 通过arrs数组创建Stream

    int[] arrs = {1,3,5,7,9};
    IntStream sm = Arrays.stream(arrs);

  • 通过集合对象创建Stream

    List list = Arrays.asList(1, 2, 3, 4, 56);
    Stream sm2 = list.stream();

/**
 * 讲解Stream流
 * IO流是操作文件流
 * Stream操作数组或者集合的流
 * 注意:Stream只操作数据,不保存数据
 *
 */
public class StreamDemo {
    public static void main(String[] args) {
        // 1、创建Stream
        // 1)、通过Arrays
        int[] arrs = {1,3,5,7,9};
        IntStream sm = Arrays.stream(arrs);// 通过arrs数组创建Stream
        // sm是Stream流对象,sm操作的数据源是arrs

        // 2)、通过集合对象
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 56);
        Stream<Integer> sm2 = list.stream(); // 创建Stream对象
        
        // 3)、Stream里面的of方法
        Stream.of(1, 2, 3, 4, 5, 6);


    }
}
  • Stream流(重点)

    把数组和集合作为操作数据源

    • 创建Stream流对象
      1. 通过arrs数组创建Stream
      2. 通过集合对象创建Stream
  • 操作流的方法

    • Stream流的操作步骤:
      创建流对象(指定流操作数据源)
      操作流:过滤,切片,跳过,截取,去重,排序
      结束流:遍历、收集、统计

    操作流方法:

    filter(过滤的条件:函数式接口):将不满足条件的数据过滤掉 (Predicate:断言型的接口)

    limit(long 数字):截取流里面多个数据
    limit(3)
    .limit(3L) // 限制流里面显示的条数
    skip():跳过几条
    .skip(2L) // 跳过前两条
    .limit(4L) // 限制显示4条

    .distinct():去除重复

    .sorted():排序,进行排序数据必须实现Comparable
    .sorted() // 排序(升序)
    .sorted(Comparator):根据定制排序

    .map():切片(给你一种类型,变为另一种类型)

    结束流方法:注意:(结束流方法只能三选一)

    1. collect():收集
      collect(Collectors.toList()); // 将结果收集为一个集
    2. .count():统计个数
    3. forEach():遍历 (Consumer:消费型的接口)
public class StreamDemo2 {
    public static void main(String[] args) {
        // 1、创建流
//        IntStream stream = Arrays.stream(new int[]{1,8,6,8,10,12,14,16, 2, 3, 4, 5, 8,6,8,10,12,14,16});// 调用一个方法
//        List list = Arrays.asList(1, 8, 6, 8, 10, 12, 14, 16, 2, 3, 4, 5, 8, 6, 8, 10, 12, 14, 16);
//        Stream stream = list.stream();
//        // 2、操作流
//        stream
//                .filter(a -> a % 2 == 0) // Predicate:断言型的接口
//                filter(a -> a >= 4)
//                .distinct() // 去除重复数据
//                .sorted((o1,o2) -> o2 - o1) // 降序排列
//                .forEach(System.out::println); // Consumer:消费型的接口

            // 将字符串里面数字降序输出,去重
        String str = "12,34,67,5,90,23,4,67,8,9";
        String[] split = str.split(",");
        Stream<String> stream = Arrays.stream(split); // 创建流
        // 将字符串变成int
        long count = stream
                .map(Integer::parseInt) // Function,将a由String转换int
                .distinct() // 去重
                .sorted((o1, o2) -> o2 - o1)
                .count();// 统计流里面个数
        System.out.println(count);

    }
}

小结Stream流
Stream流的分类
1、串行流:单线程使用(使用最多)
2、并行流:多线程使用

1、创建流
Arrays.stream(数组)
集合对象.stream()
Stream.of(可变参数)

2、流操作的方法:
filter()
limit()
skip()
sorted()
distinct()
map()

forEach()
 collect()
 count();
    public static void main(String[] args) {
        // 创建一个串行流
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
//        Stream stream = list.stream();// 创建的串行流
//        stream.forEach(System.out::println);

        // 并行流
        Stream<Integer> integerStream = list.parallelStream();
        integerStream.forEach(System.out::println);
    }
}
  • Stream的案例
public class StreamDemo4 {
    public static void main(String[] args) {
        // 1.有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新数组
//        String[] names = new String[]{"黄药师", "冯蘅", "郭靖", "黄蓉", "郭芙", "郭襄", "郭破虏"};
//        Stream stream = Arrays.stream(names);
//        Object[] array = stream.filter(a -> a.startsWith("郭")).toArray();
//        Arrays.stream(array).forEach(System.out::println);

        // 2.已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},使用Stream
//        ArrayList arrayList = new ArrayList<>();
//        arrayList.add("陈玄风");
//        arrayList.add("梅超风");
//        arrayList.add("陆乘风");
//        arrayList.add("曲灵风");
//        arrayList.add("武眠风");
//        arrayList.add("冯默风");
//        arrayList.add("罗玉风");
//        Stream stream1 = arrayList.stream();
        //1、取出前2个元素并在控制台打印输出。
//        stream1.limit(2).forEach(System.out::println);
        //2、取出后2个元素并在控制台打印输出。
//        stream1.skip(arrayList.size() - 2).forEach(System.out::println);
//        Collections.reverse(arrayList);
//        arrayList.stream().limit(2).forEach(System.out::println);

          ArrayList<String> manArray = new ArrayList<>();
                manArray.add("刘德华");
                manArray.add("成龙");
                manArray.add("吴彦祖");
                manArray.add("周润发");
                manArray.add("周星驰");
                manArray.add("吴京");

                ArrayList<String> womanList = new ArrayList<>();
                womanList.add("林心如");
                womanList.add("孙俪");
                womanList.add("柳岩");
                womanList.add("林青霞");
                womanList.add("王祖贤");
                womanList.add("张曼玉");
        //1、筛选出前一个姓林的女演员
//        womanList.stream().filter(a -> a.startsWith("林")).limit(1).forEach(System.out::println);
        //2、男演员只要名字为3个字的前三人;
//        manArray.stream().filter(a -> a.length() == 3).limit(3).forEach(System.out::println);
        //    3、把上述过滤后的男演员姓名和女演员姓名合并到一起
        List<String> collect = manArray.stream().filter(a -> a.length() == 3).limit(3).collect(Collectors.toList());
        List<String> collect1 = Stream.concat(collect.stream(), womanList.stream()).collect(Collectors.toList());
        collect1.stream().forEach(System.out::println);
        //    4、把上一步操作后的元素作为构造方法的参数创建演员对象,遍


    }

}

单元测试

测试:检查代码有没有bug
黑盒测试:不看代码结构,只看结果
白盒测试:必须要看代码
灰盒测试:能看一部分代码
**注:**上面的测试是专业人员操作的

单元测试:测试自己写方法,程序员自己测
使用main方法来做,每一个只有一个main,测试很不方便
使用单元测试来代替main

  • 需要使用一个@Test的注解
  • 第一次使用需要导包
  • (重复的代码)需要使用一个@Before或者@After的注解
    • @Before:在每个测试方法执行之前要执行方法
    • @After:在每个测试方法执行之后要执行方法
  • 注意:单元测试的方法,不能有返回值,可以抛出Exception
public class TestCase {
    @Test // 单元测试的注解
    // 单元测试的方法,不能有返回值,可以抛出Exception
    public void testDemo1() throws Exception {
        System.out.println("这个单元测试1");
    }
    @Test
    public void testDemo2() throws Exception {

        System.out.println("这个单元测试2");
    }
    @Test
    public void testDemo3() throws Exception {

        System.out.println("这个单元测试3");
    }
    // 在测试方法代码冗余(重复的代码)
    @Before // 在每个测试方法执行之前要执行方法
    public void before() throws Exception {
        System.out.println("hello");
    }

    @After
    public void after() throws  Exception {
        System.out.println("用来释放锁,关闭流");
    }


}

单例模式

一个类就是只有一个对象,那么就是单例
将一个类设计成单例的方式就是单例模式

怎样将一个类设计为单例
1、私有构造方法
2、在当前类创建对象
3、在该类设计一个类方法,返回这个对象

package cn.itsource.singleton;

/**
 * 将Dog设计为单例:饿汉模式
 */
public class Dog {
    // 2、创建对象
    private static Dog d = new Dog(); // 不管这个对象用不用,在内存中存在
    // 省略属性
    // 1、私有化构造方法
    private Dog() {}

    // 3、设计一个类方法,返回创建的对象
    public static Dog getInstance() {
        return d;
    }
}
public class SingletonDemo {
    public static void main(String[] args) {
        Dog d1 = Dog.getInstance();
        System.out.println(d1);
        Dog d2 = Dog.getInstance();
        System.out.println(d2);
        Dog d3 = Dog.getInstance();
        System.out.println(d3);
    }
}

你可能感兴趣的:(单元测试,单例模式,java,开发语言)