一、集合排序

1、集合排序API

(1)集合排序概述

元素之间的比较可以是数字大小的比较、字符串的字典比较、对象的属性比较等,在java中实现集合排序的方式可以分为两大类

  • 使用集合排序API
  • 使用支持自动排序的集合

(2)Collections.sort()方法

集合的工具类,提供了很多便于操作集合的方法,其中sort()方法用于排序

方法定义为:void sort(List list),对集合元素进行自然排序(按照元素的由小至大的顺序)

/**
 * @document: 集合中元素的排序
 * @Author:SmallG
 * @CreateTime:2023/8/8+14:05
 */

public class Demo01 {
    public static void main(String[] args) {
        //创建一个List集合
        List<Integer> list = new ArrayList<>();
        Random random = new Random();
        //产生随机的数字
        //往集合中随机保存十个数据
        for (int i = 0; i < 10; i++) {
            list.add(random.nextInt(100) + 1);
        }
        //显示集合中的数据
        System.out.println(list);
        //排序
        Collections.sort(list);
        System.out.println(list);
    }
}

(3)Comparable接口

用于定义其子类是可以比较大小的,是比较大小的前提,在使用Collections.sort()这个方法的时候,排序的元素都必须是Comparable接口的实现类,Comparable接口有个用于比较大小的抽象方法compareTo,在使用compareTo(T t)方法时返回一个整数:

  • 返回值 > 0时,表示当前对象比参数给定的对象大
  • 返回值 < 0时,表示当前对象比参数给定的对象小
  • 返回值 = 0时,表示当前对象和参数给定的对象相等
/**
 * @document: 集合中元素的排序
 * @Author:SmallG
 * @CreateTime:2023/8/8+14:05
 */

public class Demo01 {
    public static void main(String[] args) {
        Student student1 = new Student("Tom", 18);
        Student student2 = new Student("Jerry", 16);
        Student student3 = new Student("SmallG", 21);
        System.out.println("student1与student2比较:" + student1.compareTo(student2));
        System.out.println("student2与student3比较:" + student2.compareTo(student3));

        //构建集合
        List<Student> list1 = Arrays.asList(student1, student2, student3);
        //排序
        System.out.println(list1);
        // [Student{name='Tom', age=18}, Student{name='Jerry', age=16}, Student{name='SmallG', age=21}]
        Collections.sort(list1);
        System.out.println(list1);
        // [Student{name='Jerry', age=16}, Student{name='SmallG', age=21}, Student{name='Tom', age=18}]


    }

}

class Student implements Comparable<Student> {
    String name;
    int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Student o) {
        int c = this.name.charAt(0) - o.name.charAt(0);
        return c;
    }
}

(4)comparator接口

用于定义比较逻辑,可用于在集合外部元素的比较逻辑

核心方法:compare()方法,用于比较两个元素的大小

int compare(T o1,T o2)

实现compare()方法返回值要求,判断字符串时,首字母相同按第二个字符进行排序

  • 若o1 > o2则返回值 > 0
  • 若o1 < o2则返回值 < 0
  • 若o1 == o2则返回值 = 0
/**
 * @document: Comparator接口比较逻辑
 * @Author:SmallG
 * @CreateTime:2023/8/8+15:04
 */

public class Demo03 {
    public static void main(String[] args) {
        Student student1 = new Student("Tom", 18);
        student1.score = 85.6;
        Student student2 = new Student("SmallG", 14);
        student2.score = 85.5;
        Student student3 = new Student("SmallY", 21);
        student3.score = 75.6;

        //构建List集合
        List<Student> list = Arrays.asList(student1, student2, student3);
        System.out.println(list);
        //[Student{name='Tom', age=18, score=85.6}, Student{name='SmallG', age=14, score=85.5}, Student{name='SmallY', age=21, score=75.6}]
        //排序 临时使用年龄进行排序 ,匿名内部类
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.age - o2.age;
            }
        });
        System.out.println(list);
        //[Student{name='SmallG', age=14, score=85.5}, Student{name='Tom', age=18, score=85.6}, Student{name='SmallY', age=21, score=75.6}]

        //按照年龄从大到小排
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.age - o1.age;
            }
        });
        System.out.println(list);
        //[Student{name='SmallY', age=21, score=75.6}, Student{name='Tom', age=18, score=85.6}, Student{name='SmallG', age=14, score=85.5}]

        //自定义临时排序规则,按照名字进行排序
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //String类已经实现了Comparable的接口
                return o1.name.compareTo(o2.name);
            }
        });
        System.out.println(list);
        //[Student{name='SmallG', age=14, score=85.5}, Student{name='SmallY', age=21, score=75.6}, Student{name='Tom', age=18, score=85.6}]

        //按照成绩从小到大排列
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                if (o1.score-o2.score>0){
                    return 1;
                }else if (o1.score-o2.score<0){
                    return -1;
                }else{
                    return 0;
                }
            }
        });
        System.out.println(list);
        //[Student{name='SmallY', age=21, score=75.6}, Student{name='SmallG', age=14, score=85.5}, Student{name='Tom', age=18, score=85.6}]
    }
}

其他方法:

reversed():返回当前比较器的逆序比较器,将它原来的比较规则进行颠倒。

thenComparing(Comparator< ? super T > other):返回一个组合比较器,用于对两个比较规则进行联合排序,如果原始比较器认为两个元素相等,则使用传入的other比较器进一步比较

/**
 * @document: Comparator的其他方法
 * @Author:SmallG
 * @CreateTime:2023/8/8+15:39
 */

public class Demo02 {
    public static void main(String[] args) {
        Student student1 = new Student("Tom", 18);
        student1.score = 85.6;
        Student student2 = new Student("SmallG", 18);
        student2.score = 85.5;
        Student student3 = new Student("SmallY", 21);
        student3.score = 75.6;

        //构建List集合
        List<Student> list = Arrays.asList(student1, student2, student3);

        //定义一个比较器,年龄升序的比较规则
        Comparator<Student> c1 = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.age - o2.age;
            }
        };

        //定义一个年龄降序的比较器,如果年龄相等按照添加的顺序进行排列
        Comparator<Student> c2 = c1.reversed();
        //先升序pail
        Collections.sort(list, c1);
        System.out.println("年龄升序排列:" + list);
        Collections.sort(list, c2);
        System.out.println("年龄降序排列:" + list);

        //如果在年龄一样的情况下按照名字比较,组合使用比较器
        Comparator<Student> c3 = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.name.compareTo(o2.name);
            }
        };

        //声明一个组合比较器 先按照年龄比较,如果年龄相同按照名字比较
        Comparator<Student> c4 = c1.thenComparing(c3);
        Collections.sort(list, c4);
        System.out.println(list);
    }
}

2、自动排序的集合

(1)树数据结构

一种非线性数据结构,由一组节点和节点之间的连接关系(边)组成

树数据结构

(2)二叉搜索树

  • 对于根节点,左子树中所有节点的值 < 根节点的值 < 右子树中所有节点的值
  • 任意节点的左、右子树也是二叉搜索树

(3)红黑树

红黑树通过遵守以下五条规则来保持树的平衡性

  • 每个节点要么是红色,要么是黑色
  • 根节点是黑色
  • 每个叶子节点都是黑色
  • 如果一个节点是红色的,则其两个子节点必须都是黑色的
  • 从任意节点到其每个叶子节点的简单路径上,黑色节点的数量相同

(4)TreeMap

  • 基于红黑树数据结构实现
  • 键的有序性,键的排序可以是按照键类型的自然排序或者通过传入的Comparator对象来定义
  • 查找效率:由于红黑树是一种自平衡的二叉搜索树,treeMap中的查找、插入和删除操作的时间复杂度都是O(log n),其中n是映射中键值对的数量。
  • 允许null键:要注意在自定义比较器中处理null键的情况,否则可能导致异常

TreeMap

/**
 * @document: TreeMap
 * @Author:SmallG
 * @CreateTime:2023/8/8+16:30
 */

public class Demo04 {
    public static void main(String[] args) {
        //创建TreeMap集合对象
        TreeMap<Integer, String> treeMap = new TreeMap<>();
        treeMap.put(5, "Tom");
        treeMap.put(3, "Jerry");
        treeMap.put(9, "SmallG");
        treeMap.put(2, "SmallY");

        //遍历集合
        for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {
            System.out.println("Key:" + entry.getKey() + " Value: " + entry.getValue());
        }
        System.out.println("________________________________________");
        //返回临近的较大键值对 8
        Map.Entry<Integer, String> entry1 = treeMap.higherEntry(8);
        System.out.println("临近8的较大键值对:" + entry1);

        //返回临近的较小键值对
        Map.Entry<Integer, String> entry2 = treeMap.lowerEntry(8);
        System.out.println("临近8的较小键值对:" + entry2);

        //获取TreeMap的子集(from,to) ,返回的结果是from和to之间,左闭右开
        SortedMap<Integer, String> sortedMap = treeMap.subMap(3, 5);
        System.out.println(sortedMap);

        //可以设置是否包含边界(from或者to)
        NavigableMap<Integer, String> map = treeMap.subMap(3, false, 5, true);
        System.out.println(map);
        System.out.println("_______________________________");

        //返回逆序集合
        System.out.println(treeMap.descendingMap());
    }
}

(5)TreeSet

实现了SortedSet接口的有序集合,底层使用了一个TreeMap的key来存储所有的元素,TreeSet中不允许包含重复元素。

/**
 * @document: TreeSet集合
 * @Author:SmallG
 * @CreateTime:2023/8/8+16:51
 */

public class Demo05 {
    public static void main(String[] args) {
        //创建员工对象
        Employee emp1 = new Employee("Tom", 18);
        Employee emp2 = new Employee("Jerry", 16);
        Employee emp3 = new Employee("SmallG", 20);
        Employee emp4 = new Employee("SmallY", 22);

        TreeSet<Employee> set1 = new TreeSet<>();
        set1.add(emp1);
        set1.add(emp2);
        set1.add(emp3);
        set1.add(emp4);
        System.out.println("set1" + set1);

        //定义排序规则 名字升序排列
        Comparator<Employee> c = new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                return o1.name.compareTo(o2.name);
            }
        };

        //创建一个自定义排序规则
        TreeSet<Employee> set2 = new TreeSet<>(c);
        set2.addAll(set1);
        System.out.println(set2);
    }
}

class Employee implements Comparable<Employee> {
    String name;
    int age;

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Employee o) {
        return this.age - o.age;
    }
}

二、Lambda和Stream

1、Lambda表达式

允许代码块作为参数传递给方法或者作为返回值在方法中返回,是一个匿名函数,可以像普通方法一样传递参数并执行代码,使用 "->" 来将参数列表和方法体分开。好处 :用于简化代码,增强代码的可读性。

(1)函数接口:只有一个抽象方法的接口

用@FunctionalInterface注解标识,使用这个注解后只能定义一个方法。

/**
 * @document: 声明一个函数式接口
 * @Author:SmallG
 * @CreateTime:2023/8/9+9:34
 */

@FunctionalInterface
public interface MyFunction {
    int apply(int x, int y);
}

(2)基于Lambda表达式实现函数接口

/**
 * @document: 实现MyFunction方法,两数加法
 * @Author:SmallG
 * @CreateTime:2023/8/9+9:39
 */

public class Demo07 {
    public static void main(String[] args) {
        //匿名内部类
        MyFunction add1 = new MyFunction() {
            @Override
            public int apply(int x, int y) {
                return x + y;
            }
        };
        System.out.println(add1.apply(3, 5)); //8

        //通过Lambda表达式实现接口中的方法  (参数1,参数2) ->返回值
        MyFunction add2 = (x, y) -> x + y;
        System.out.println(add2.apply(3, 5)); //8
    }
}

(3)Lambda完整语法

参数列表:(x,y),如果只有一个参数可以省略括号

箭头:->,左侧是参数列表右侧是主体

主体:x + y,Lambda主体可以是一个表达式(不需要使用return返回)或代码块(需要return)

/**
 * @document: 实现MyFunction方法,两数加法
 * @Author:SmallG
 * @CreateTime:2023/8/9+9:39
 */

public class Demo07 {
    public static void main(String[] args) {
        //通过Lambda表达式实现接口中的方法  (参数1,参数2) ->返回值
        MyFunction add2 = (x, y) -> x + y;
        System.out.println(add2.apply(3, 5)); //8

        //完整语法
        MyFunction add3 = (x, y) -> {
            System.out.println("x=" + x + ",y=" + y);
            int sum = x + y;
            return sum;
        };
        System.out.println(add3.apply(5, 6));
        //x=5,y=6
        //11

        //方法只有一个参数,括号可以不用写
        MyFunction1 result = x -> x += 2;
        System.out.println(result.apply(2)); //4
    }
}

(4)使用Lambda过滤文件夹内容

/**
 * @document: 基于Lambda表达式实现
 * @Author:SmallG
 * @CreateTime:2023/8/9+10:29
 */

public class FilterFiles2 {
    public static void main(String[] args) {
        File file1 = new File("C:\\Program Files\\Internet Explorer");
        //使用Lambda表达式 过滤文件
        FileFilter filter = pathname -> pathname.isFile() && pathname.getName().startsWith("i");
        //获取过滤后的文件列表
        File[] files = file1.listFiles(filter);
        for (File file : files) {
            System.out.println(file.getName());
        }
    }
}

(5)函数引用

函数引用语法形式:持有者 :: 方法名

函数引用可以分为以下四种类型:

  • 静态方法引用:引用一个已有的静态方法,例如:Math :: abs
  • 类方法引用:引用一个已有的实例类型方法,例如:String :: length
  • 对象方法引用:引用一个已有的对象方法,例如:out :: println
  • 构造函数引用:引用一个已有的构造函数(使用较少)例如:ArrayList :: new
/**
 * @document: 函数式引用
 * @Author:SmallG
 * @CreateTime:2023/8/9+10:44
 */

public class Demo08 {
    public static void main(String[] args) {
        String str = "Hello World";

        //快速的获取字符串的某个字符
        //使用chatAt方法来实现Function接口的实现
        //泛型Integer是charAt方法的参数类型,Character是方法的返回值类型
        //对象方法引用
        Function<Integer, Character> function = str::charAt;
        System.out.println(function.apply(0)); //H

        //类实例方法引用
        List<String> list = Arrays.asList("Tom", "Jerry", "smallG");
        //首字母 忽略大小写排序
        Collections.sort(list, String::compareToIgnoreCase);
        System.out.println(list); //[Jerry, smallG, Tom]

        //类静态方法引用,将字符串转化为整数
        Function<String, Integer> function1 = Integer::parseInt;
        int num = function1.apply("123");
        System.out.println(num); //123

        //构造器引用 创建一个ArrayList对象,通过get方法获取这个集合对象
        Supplier<ArrayList<String>> runnable = ArrayList::new;
        ArrayList<String> list1 = runnable.get();
        list1.add("Tom");
        System.out.println(list1); //[Tom]
        
    }
}

函数式引用和Lambda表达式对比:

/**
 * @document:
 * @Author:SmallG
 * @CreateTime:2023/8/9+11:27
 */

public class Demo09 {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Tom", "Jerry", "Spike");
        //输出集合的内容
        names.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        System.out.println("———————————————————");
        //输出集合的内容
        names.forEach(s -> System.out.println(s));

        System.out.println("———————————————————");
        //函数式引用 输出集合的内容
        names.forEach(System.out::println);
    }
}

将字符串转化成大写形式:

/**
 * @document:
 * @Author:SmallG
 * @CreateTime:2023/8/9+11:36
 */

public class Demo10 {
    public static void main(String[] args) {
        String s = "hello world";
        //匿名内部类
        Function<String, String> function = new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase(Locale.ROOT); //把小写字母全部变大写
            }
        };
        System.out.println(function.apply(s));
        System.out.println("___________________________");

        //Lambda表达式实现小写变大写
        Function<String, String> function2 = s1 -> s1.toUpperCase(Locale.ROOT);
        System.out.println(function2.apply(s));
        System.out.println("___________________________");

        //使用函数式引用来实现
        Function<String, String> function3 = String::toUpperCase;
        System.out.println(function3.apply(s));
    }
}

2、Stream

(1)概述

允许在数据集上进行功能性操作,在使用流进行操作的时候,不会改变原始数据集合中的数据,而是返回一个新的流

(2)示例:找出 J 开头的名字

/**
 * @document:
 * @Author:SmallG
 * @CreateTime:2023/8/9+14:05
 */

public class Demo12 {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Tom", "Jerry", "Spike", "SmallG", "JAKE");
        //找出所有以J开头的人名
        List<String> newNames = new ArrayList<>();
        //遍历names集合
        for (String s : names) {
            if (s.startsWith("J")) {
                newNames.add(s);
            }
        }
        System.out.println(newNames); //[Jerry, JAKE]

        //使用Stream API找出以J开头的人名
        List<String> filterNames = names.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("J");
            }
        }).collect(Collectors.toList());
        System.out.println(filterNames); //[Jerry, JAKE]

        //使用lambda表达式进行简化
        List<String> filterNames2 = names.stream().filter(s -> s.startsWith("J")).collect(Collectors.toList());
        System.out.println(filterNames2); //[Jerry, JAKE]

    }
}

(3)常用的Stream API方法

  • filter:过滤流中的元素,只保留符合条件的元素
  • map:对流中的元素进行映射,将一个元素映射为另一个元素
  • flatMap:对流中的元素进行扁平化映射,将一个元素映射为多个元素
  • sorted:对流中的元素进行排序
  • distinct:去重,保留流中的不同元素
  • limit:限制流中元素的数量
  • skip:跳过流中的前N个元素
  • forEach:遍历流中的元素
  • reduce:对流中的元素进行归约,得到一个结果
  • collect:将流中的元素收集到一个集合中
  • min和max:找出流中的最小值和最大值
  • count:统计流中元素的数量
  • anyMatch、allMatch和noneMatch:判断流中的元素是否满足某一个条件
  • findFirst和findAny:找到流中的第一个元素和任意一个元素
  • parallel和sequential:切换流的并行和串行模式

(4)stream API 的使用步骤

1、创建流

2、中间操作

3、终止操作

4、并行操作:对大数据集可以用并行操作来提高效率。

示例:映射数据

  • 使用stream()方法将集合转化为流
  • 使用filter()方法筛选
  • 使用collect()方法将筛选后的结果转换为List集合
  • 使用map()方法将字符串映射为字符串长度
/**
 * @document: stream 映射数据
 * @Author:SmallG
 * @CreateTime:2023/8/9+14:27
 */

public class Demo13 {
    public static void main(String[] args) {
        //定义一个集合
        List<String> names = Arrays.asList("Tom", "Jerry", "Spike", "SmallG", "JAKE");
        //计算names集合中每个名字的长度
        List<Integer> namesLength = names.stream().map(s -> s.length()).collect(Collectors.toList());
        System.out.println(namesLength);
    }
}

示例:统计数据

  • 使用count()方法统计元素个数
  • 使用max()和min()方法求最大值和最小值
  • 使用sum()方法求元素的总和
  • 使用average()方法求元素的平均值
/**
 * @document: Stream数据统计
 * @Author:SmallG
 * @CreateTime:2023/8/9+14:43
 */

public class Demo14 {
    public static void main(String[] args) {
        List<Integer> number = Arrays.asList(4, 2, 5, 3, 1);
        long count = number.stream().count(); //统计集合中所有数据的个数
        int max = number.stream().max(Integer::compare).orElse(0);
        int min = number.stream().min(Integer::compare).orElse(0);
        int sum = number.stream().mapToInt(Integer::intValue).sum(); //求和
        double avg = number.stream().mapToInt(Integer::intValue).average().orElse(0);
        System.out.println("所有数据的个数:" + count);
        System.out.println("最大值:" + max);
        System.out.println("最小值:" + min);
        System.out.println("所有数据的和:" + sum);
        System.out.println("平均值:" + avg);

        //对数据进行排序
        List<Integer> sortList = number.stream().sorted().collect(Collectors.toList());
        System.out.println(sortList);
    }
}

三、练习

1 利用Lambda表达式过滤当前类目录中Java源文件,并且统计Java文件行数

获取当前源文件夹目录中全部Java源文件,统计每个文件的代码行数(代码行数不包含空行)。

提示:可以使用Lambda过滤当前源文件夹的文件列表,找到java源文件,再将每个文件打开统计代码行数,如果是空行可以跳过不统计。

运行效果如下图所示:

练习1

/**
 * @document: 利用Lambda表达式过滤当前类目录中Java源文件,并且统计Java文件行数
 * @Author:SmallG
 * @CreateTime:2023/8/9+11:44
 */

public class FileCount {
    public static void main(String[] args) throws IOException {
        File file = new File("src/day03");
        //使用Lambda表达式过滤文件
        FileFilter filter = pathname -> pathname.isFile() && pathname.getName().endsWith(".java");
        File[] files = file.listFiles(filter);
        int count = 0;
        for (File file1 : files) {
            FileReader fr = new FileReader(file1);
            BufferedReader br = new BufferedReader(fr);
            String line = br.readLine();
            while (line != null) {
                if (line.trim().isEmpty()) {
                    line = br.readLine();
                    continue;
                }
                count++;
                line = br.readLine();
            }
        }
        System.out.println("Java文件行数 " + count);
    }
}

2 利用Stream API 对一组学生数据按照年龄进行排序

创建Student类来表示学生,并定义name、age和grade等属性记载数据;然后创建一组学生数据,并使用Stream API对其按照年龄进行排序。

运行效果如下图所示:

练习2

/**
 * @document: 利用Stream API对一组学生数据按照年龄进行排序
 * @Author:SmallG
 * @CreateTime:2023/8/9+15:09
 */

public class StudentSortAge {
    public static void main(String[] args) {
        Student student1 = new Student("Tom", 21, 90);
        Student student2 = new Student("Jerry", 19, 78);
        Student student3 = new Student("Spike", 18, 67);
        Student student4 = new Student("SmallG", 23, 70);
        Student student5 = new Student("SmallY", 18, 98);

        List<Student> students = Arrays.asList(student1, student2, student3, student4, student5);
        List<Student> collect = students.stream().sorted(((o1, o2) -> o1.age - o2.age)).collect(Collectors.toList());
        for (Student student : collect) {
            System.out.println(student);
        }
    }
}

class Student {
    String name;
    int age;
    int grade;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", grade=" + grade +
                '}';
    }

    public Student(String name, int age, int grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
}

3 利用Stream API 计算一组学生分数平均值

创建Student类来表示学生,并定义name、age和grade等属性;然后创建一组学生数据,并使用Stream API计算其分数平均值。

运行效果如下图所示:

练习3

/**
 * @document: 利用Stream API计算一组学生分数平均值
 * @Author:SmallG
 * @CreateTime:2023/8/9+17:11
 */

public class StudentGradeAvg {
    public static void main(String[] args) {
        Student student1 = new Student("Tom", 21, 90);
        Student student2 = new Student("Jerry", 19, 78);
        Student student3 = new Student("Spike", 18, 67);
        Student student4 = new Student("SmallG", 23, 70);
        Student student5 = new Student("SmallY", 18, 98);

        List<Student> students = Arrays.asList(student1, student2, student3, student4, student5);
        List<Integer> studentGrade = new ArrayList<>();
        for (Student student : students) {
            studentGrade.add(student.grade);
        }
        double v = studentGrade.stream().mapToInt(Integer::intValue).average().orElse(0);
        System.out.println("Average grade: " + v);
    }
}
最后修改:2023 年 08 月 09 日
如果觉得我的文章对你有用,请随意赞赏