Java补充(Java8新特性)(和IO都很重要)

一、Lambda表达式

1.1、为什么使用Lambda表达式 Lambda表达式起步案例

下面源码注释是传统写法,代码是简写表达式写法

java 复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.function.Consumer;

/*
* 学什么?
*   1、Lambda表达式
*   2、Stream API
*   3、Optional类 NullPointerException
* 目前存在的问题?
*   方法不能作为参数传递
* 如何解决这个问题?
*   行为参数化
* */
public class MyTest02 {
    public static void main(String[] args) {
        //匿名内部类
        /*Thread th1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello Java8");
            }
        });
        th1.start();*/
        Thread th1 = new Thread(() -> {
            System.out.println("hello Java8");
        });
        th1.start();

        ArrayList<String> list = new ArrayList<String>();
        list.add("111111");
        list.add("11");
        list.add("11222");
        list.add("1");

        /*Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //return o1.length() - o2.length();
                return Integer.compare(o1.length(), o2.length());
            }
        });*/
        // -> 后省略了大括号和return 还有o1,o2的String
        Collections.sort(list, (o1,o2) -> Integer.compare(o1.length(), o2.length()));
        System.out.println(list);

        /*list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {//s -- 每次被遍历到的元素
                System.out.println(s);
            }
        }); 下面是简写后的*/
        list.forEach(s -> System.out.println(s));
        list.forEach(System.out::println);
    }
}

1.2、Lambda表达式写法

Lambda表达式是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格。使Java的语言表达能力得到了提升。

语法:

Lambda表达式操作符或箭头操作符:->

左侧:指定了Lambda表达式需要的参数列表(其实就是接口中的抽象方法的形参列表)

右侧:指定了Lambda体,是抽象方法的实现逻辑,也即Lambda表达式要执行的功能(其实就是重写的抽象方法的方法体)。

先把匿名内部类的对象找出来,再看方法参数和方法体

即源码

java 复制代码
package day33;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.function.Consumer;

/*
* 学什么?
*   1、Lambda表达式
*   2、Stream API
*   3、Optional类 NullPointerException
* 目前存在的问题?
*   方法不能作为参数传递
* 如何解决这个问题?
*   行为参数化
* Lambda表达式
*   -> Lambda操作符或箭头操作符
*   左侧:方法的参数列表
*   右侧:方法的方法体
*   方法:重写的方法
* Lambda表达式简写/进阶写法
*   1、如果参数列表没有参数,要写成()
*   2、如果参数列表有参数
*     参数个数>=2 (数据类型1 参数名1,数据类型2 参数名2,数据类型3 参数名3)
*     参数个数>=2 (参数名1, 参数名2,参数名3) !!!!!
*     只有一个参数 (数据类型 参数名)
*     只有一个参数 (参数名)
*     只有一个参数 参数名 !!!!!
*   3、右侧 - 如果方法体有多行代码,必需写{}
*   4、右侧 - 如果方法体只有一行代码,不用写{},不用写return,不用写结尾的";"
 * */
public class MyTest02 {
    public static void main(String[] args) {
        //匿名内部类
        /*Thread th1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello Java8");
            }
        });
        th1.start();*/
        Thread th1 = new Thread(() -> {
            System.out.println("hello Java8");
        });
        th1.start();

        ArrayList<String> list = new ArrayList<String>();
        list.add("111111");
        list.add("11");
        list.add("11222");
        list.add("1");

        /*Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //return o1.length() - o2.length();
                return Integer.compare(o1.length(), o2.length());
            }
        });*/
        // -> 后省略了大括号和return 还有o1,o2的String
        Collections.sort(list, (o1,o2) -> Integer.compare(o1.length(), o2.length()));
        System.out.println(list);

        /*list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {//s -- 每次被遍历到的元素
                System.out.println(s);
            }
        }); 下面是简写后的*/
        list.forEach(s -> System.out.println(s));
        list.forEach(System.out::println);
    }
}

1.3、函数式接口_@Functional注解

复制代码
@FunctionalInterface
@Override
作用:编译器帮我们检查标注了该注解的接口是不是函数式接口
      |-- 是 -- 编译通过
      |-- 不是 -- 无法编译通过
      注意:该注解的作用只是检查的作用,可以不写

相关源码显示:

java 复制代码
package day33;

public class MyTest03 {
    public static void aaa(MyInterface a, int m , int n) {
        a.test(m,n);
    }

    public static void main(String[] args) {
        /*aaa(new MyInterface() {
            @Override
            public void test(int a, int b) {
                System.out.println(a + ":" + b);
            }
        },1,2);*/
        aaa((a,b) -> System.out.println(a + ":" + b),1,2);
    }
}
java 复制代码
package day33;

@FunctionalInterface
public interface MyInterface {
    void test(int a , int b);
    //唯一的一个抽象方法
}

---------------------自己定义的,Java官方也有

1.4、函数式接口_常见函数式接口说明

1.5、复合的Lambda表达式

比较器复合 和 谓词复合

java 复制代码
package day34;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Predicate;

//比较器复合
public class MyTest02 {
    public static void main(String[] args) {
        ArrayList<Apple> list = new ArrayList<>();

        list.add(new Apple(150,"red"));
        list.add(new Apple(210,"red"));
        list.add(new Apple(300,"yellow"));
        list.add(new Apple(90,"green"));
        list.add(new Apple(90,"yellow"));
        list.add(new Apple(100,"green"));
        list.add(new Apple(123,"red"));

        //按照重量降序排序
        //list.sort(Comparator.comparing(Apple::getWeight).reversed());
        //按照重量降序排序,如果重量相同那就按照颜色的升序排序
        /*list.sort(Comparator.
                comparing(Apple::getWeight)
                .reversed()
                .thenComparing(Apple::getColor));*/
        //.thenCompareing(Comparator.comparing(Apple::getColor).reversed()));
        //list.removeIf(item -> item.getWeight() == 90);
        //删除颜色不是红颜色的苹果 Predicate的复合即谓词复合
        Predicate<Apple> redApple = item -> item.getColor().equals("red");
        //list.removeIf(redApple.negate());
        //去除红颜色并且重量大于150的苹果
        list.removeIf(redApple.and(item -> item.getWeight() > 150));
        //去除红色并且重量大于150的苹果或绿苹果
        list.removeIf(redApple.and(item -> item.getWeight() > 150).or(item -> item.getColor().equals("green")));
        list.forEach(System.out::println);
    }
}

二、方法引用

1、本质:就是Lambda表达式,对Lambda表达式的简写

2、比如类名::方法名,一般带两个冒号的就是

什么情况下Lambda表达式可以改成方法引用?

1)Lambda表达式的方法体只有一行代码,并且只调用了一个方法

2)除了参数列表和1)中的"一个方法",没有再引入其他的额外的内容

三、Stream_中间操作

3.1、filter 过滤符合条件的

java 复制代码
package day34;

import java.util.ArrayList;

public class MyTest04 {
    public static void main(String[] args) {
        //filter -- 中间操作
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        //在控制台打印长度大于2的字符串
        list.stream()
                .filter(item -> item.length() > 2) //--> Stream
                .forEach(System.out::println);
        System.out.println("--------------------------------");


        System.out.println(list);
    }
}

3.2、distinct 去重

java 复制代码
import java.util.ArrayList;

public class MyTest04 {
    public static void main(String[] args) {
        //filter -- 中间操作
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        //在控制台打印长度大于2的字符串
        /*list.stream()
                .filter(item -> item.length() > 2) //--> Stream
                .forEach(System.out::println);
        System.out.println("--------------------------------");
*/
        //去除重复
        list.stream()
                .distinct() //根据元素的equals和hashCode方法判断是否重复
                .forEach(System.out::println);
        System.out.println("--------------------------------");

        ArrayList<Apple> list1 = new ArrayList<>();

        list1.add(new Apple(150,"red"));
        list1.add(new Apple(210,"red"));
        list1.add(new Apple(300,"yellow"));
        list1.add(new Apple(90,"green"));
        list1.add(new Apple(90,"yellow"));
        list1.add(new Apple(90,"yellow"));
        list1.add(new Apple(100,"green"));
        list1.add(new Apple(123,"red"));
        
        list1.stream()
                .distinct()
                .forEach(System.out::println);

        
    }
}

3.3、limit 截断流 使其元素不超过给定数量

java 复制代码
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        list1.stream()
                .limit(3)
                .forEach(System.out::println);

3.4、skip 跳过元素,返回一个扔掉了前n个元素的流,若元素不足n个,返回空流

java 复制代码
 list1.stream()
      .skip(3)
      .forEach(System.out::println);

3.5、map 映射 将流中的每个元素进行转换

3.5.1、传统做法

java 复制代码
package day34;

import java.util.ArrayList;
import java.util.LinkedHashSet;

public class MyTest05 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        //map - 映射 - 将流中的每个元素进行转换
        //获取list中每个字符串的长度并在控制台打印
        list.stream()//String
                .map(s -> s.length())//长度
                .forEach(System.out::println);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        //获取list中每个字符串的长度并在控制台打印,去除重复的长度
        list.stream()
                .map(String::length)
                .distinct()
                .forEach(System.out::println);
        System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        //传统做法
        LinkedHashSet<Integer> setLength = new LinkedHashSet<>();
        for (String s : list) {
            setLength.add(s.length());
        }
        for (Integer len : setLength) {
            System.out.println(len);
        }
    }
}

3.5.2、flatMap 把多个流合并成一个流

java 复制代码
System.out.println("__________________________________________");

        list.stream()
                .mapToInt(String::length)
                .distinct()
                .forEach(System.out::println);

        ArrayList<String> list1 = new ArrayList<>();
        list1.add("Hello");
        list1.add("World"); //H e l l o W o r l d

        list1.stream() //String
                .map(s -> s.split("")) //String --> String[]
                .flatMap(arr -> Arrays.stream(arr)) //String[] --> Stream -->Stream合并
                .forEach(System.out::println);
        /* 传统的 上面的是新的
        String[] arr = "hahaha".split("");
        System.out.println(Arrays.toString(arr));*/

四、Stream_终端操作

补forEach:没有返回值

4.1、allMatch_anyMatch_noneMatch

java 复制代码
package day34;

import java.util.ArrayList;


public class MyTest06 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        //list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        boolean flag = list.stream()
                .allMatch(s -> s.length() > 2); //判断所有元素是否达到要求
        System.out.println(flag);

        boolean flag1 = list.stream()
                .anyMatch(s -> s.length() > 2); //判断是否有元素是否达到要求
        System.out.println(flag1);

        boolean flag2 = list.stream()
                .noneMatch(s -> s.length() > 2); //判断没有任何元素达到要求
        System.out.println(flag2);
    }
}

4.2、findFirst_findAny

java 复制代码
package day34;

import java.util.ArrayList;
import java.util.Optional;

public class MyTest06 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        //list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        boolean flag = list.stream()
                .allMatch(s -> s.length() > 2); //判断所有元素是否达到要求
        System.out.println(flag);

        boolean flag1 = list.stream()
                .anyMatch(s -> s.length() > 2); //判断是否有元素是否达到要求
        System.out.println(flag1);

        boolean flag2 = list.stream()
                .noneMatch(s -> s.length() > 2); //判断没有任何元素达到要求
        System.out.println(flag2);

        Optional<String> first = list.stream().findFirst(); //获取第一个元素
        System.out.println(first.get());

        Optional<String> any = list.stream().findAny(); //获取任意一个元素
        System.out.println(any.get());
    }
}

4.3、reduce

!!!!!归约!!!!!

之前见到过的终端操作都是返回一个boolean(allMatch之类的)、void(forEach)或Optional对象(findAny)等。使用reduce操作来表达更复杂的查询,此类查询需要将流中所有元素反复结合起来,得到一个值,比如一个Integer.这样的查询可以被归类为归约操作(将流归约成一个值)

java 复制代码
package day34;

import java.util.Arrays;
import java.util.Optional;

public class MyTest07 {
    public static void main(String[] args) {
        Integer[] arr = new Integer[]{1,2,3};
        /*Integer sum = Arrays.stream(arr)
                .reduce(0, (n1, n2) -> n1 + n2);*/

        /*Integer sum = Arrays.stream(arr)
                .reduce(0, (n1, n2) -> Integer.sum(n1, n2));*/

        Integer sum = Arrays.stream(arr)
                .reduce(0, Integer::sum);
        System.out.println(sum);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        Optional<Integer> sum1 = Arrays.stream(arr)
                .reduce(Integer::sum);
        System.out.println(sum1.get());
        
        //最大值
        /*Integer max = Arrays.stream(arr)
                .reduce(arr[0], (n1, n2) -> {
                    if (n1 > n2) {
                        return n1;
                    } else {
                        return n2;
                    }
                });*/
       /* Integer max = Arrays.stream(arr)
                .reduce(arr[0], (n1, n2) -> n1 > n2 ? n1 : n2);*/
        /*Integer max = Arrays.stream(arr)
                .reduce(arr[0], (n1, n2) -> Integer.max(n1, n2));*/
        Integer max = Arrays.stream(arr)
                .reduce(arr[0], Integer::max);
        System.out.println("Max = " + max);

        Optional<Integer> max1 = Arrays.stream(arr)
                .reduce(Integer::max);//没有起始值的
        System.out.println("Max1 = " + max1.get());
        
        //最小值
        Integer min = Arrays.stream(arr)
                .reduce(arr[0], Integer::min);
        System.out.println("Min = " + min);
        
        //最佳实践:包装类判断值是否相同要使用equals判断
        Integer i1 = 1000;
        Integer i2 = 1000;
        System.out.println(i1 == i2);//不行
        System.out.println(i1.equals(i2));
    }
}

小练习:

怎样用map 和 reduce 方法计算流中元素的数据。

java 复制代码
 //计算流中的元素个数
        //把元素值都变成1,累加起来即为sum
        Integer count = Arrays.stream(arr)
                .map(item -> 1)
                .reduce(0, Integer::sum);
        System.out.println(count);

4.4、sorted

java 复制代码
package day34;

import java.util.ArrayList;
import java.util.Comparator;

public class MyTest08 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        //list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");
        
        list.stream()
                .sorted() //自然排序
                .forEach(System.out::println);
        System.out.println("==============================================");
        
        /*list.stream()
                .sorted((s1, s2) -> Integer.compare(s1.length(), s2.length()))
                .forEach(System.out::println);*/
        list.stream()
                .sorted(Comparator.comparingInt(String::length).reversed().thenComparing(String::compareTo))
                .forEach(System.out::println);

        System.out.println("-----------------------------------------------");
        System.out.println(list.stream().count());

    }
}

4.5、Stream的终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值。例如:List、Integer,甚至是void。

流进行了终止操作后,不能再次使用。

java 复制代码
package day35;

import java.util.ArrayList;
import java.util.stream.Stream;

public class MyTest01 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        Stream<String> stream = list.stream();
        stream.map(item -> 1).forEach(System.out::println);
        //流一旦进行了终端操作就不能再重复使用,报错
        stream.map(item -> 1).forEach(System.out::println);
    }
}

4.5.1、匹配与查找

java 复制代码
package day35;

import java.util.ArrayList;
import java.util.Optional;
import java.util.stream.Stream;

public class MyTest01 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        System.out.println(list.stream().count());

        Optional<String> max = list.stream()
                //.max((s1, s2) -> s1.compareTo(s2));
                .max(String::compareTo);
        System.out.println(max.get());
    }
}

4.6、collect

java 复制代码
package day35;

import java.util.*;
import java.util.stream.Collectors;

public class MyTest02 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Aqaa");
        list.add("Bssss");
        list.add("Cwww");
        list.add("Ddsdd");
        list.add("Edadc");

        /*ArrayList<Integer> nums = new ArrayList<>();
        list.stream()
                .map(String::length)
                .forEach(len -> nums.add(len));
        System.out.println(nums);*/

        List<Integer> nums = list.stream()
                .map(String::length)
                .collect(Collectors.toList());//把流当中的元素给搜集到集合里面,并作为元素返回
        Set<Integer> nums1 = list.stream()
                .map(String::length)
                .collect(Collectors.toSet());//Set方法自动去重,Collectors可省略

        TreeSet<Integer> num2 = new TreeSet<>(nums1);//合并转换
        System.out.println(num2);

        System.out.println(nums1);
        System.out.println("------------------------------------------------");
        String s = list.stream()
                .map(str -> str.substring(0, 1))
                .collect(Collectors.joining("+"));
        System.out.println(s);

        //例子:搜集所有参与交易的交易员姓名到一个集合中
        /*List<String> names = transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getName)
                .distinct
                .collect(Collectors.toList());
        System.out.println(names);*/

    }
}
相关推荐
叶 落几秒前
[Java 基础]选英雄(配置 IDEA)
java·ide·intellij-idea
陈丹阳(滁州学院)几秒前
解决idea编译运行项目时间长的问题
java·intellij-idea·idea
小伍_Five36 分钟前
Spark实战能力测评模拟题精析【模拟考】
java·大数据·spark·scala·intellij-idea
阿蒙Amon1 小时前
C#获取磁盘容量:代码实现与应用场景解析
开发语言·c#
橘子青衫1 小时前
Java多线程编程:深入探索线程同步与互斥的实战策略
java·后端·性能优化
界面开发小八哥1 小时前
VS代码生成工具ReSharper v2025.1——支持.NET 10和C# 14预览功能
开发语言·ide·c#·.net·visual studio·resharper
胡西风_foxww2 小时前
Python 入门到进阶全指南:从语言特性到实战项目
开发语言·python·快速入门
bubiyoushang8882 小时前
matlab实现高斯烟羽模型算法
开发语言·算法·matlab
CN.LG2 小时前
C# 从 ConcurrentDictionary 中取出并移除第一个元素
java·开发语言·c#
重庆小透明2 小时前
【从零学习JVM|第二篇】字节码文件
java·jvm·学习