Java8流式编程详解

news2024/11/16 6:31:08

简介

java8提供的流式编程使得我们对于集合的处理不再是临时集合加上各种还能for循环,取而代之的是更加简洁高效的流水线操作,所以笔者就以这篇文章总结一下流式编程中常见的操作。

前置铺垫

后文示例操作中,我们都会基于这个菜肴类的集合展开,对于菜肴类的代码如下:

public class Dish {

    /**
     * 名称
     */
    private final String name;
    /**
     * 是否是素食
     */
    private final boolean vegetarian;
    /**
     * 卡路里
     */
    private final int calories;
    /**
     * 类型
     */
    private final Type type;

    //类型枚举 分别是是:肉类 鱼类 其他
    public enum Type {MEAT, FISH, OTHER}

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }


    @Override
    public String toString() {
        return name;
    }


}

同理我们也给出集合声明和初始化代码段:

 public static final List<Dish> menu =
            Arrays.asList(new Dish("pork", false, 800, Dish.Type.MEAT),
                    new Dish("beef", false, 700, Dish.Type.MEAT),
                    new Dish("chicken", false, 400, Dish.Type.MEAT),
                    new Dish("french fries", true, 530, Dish.Type.OTHER),
                    new Dish("rice", true, 350, Dish.Type.OTHER),
                    new Dish("season fruit", true, 120, Dish.Type.OTHER),
                    new Dish("pizza", true, 550, Dish.Type.OTHER),
                    new Dish("prawns", false, 400, Dish.Type.FISH),
                    new Dish("salmon", false, 450, Dish.Type.FISH));

元素的筛选

常规过滤筛选

菜肴类的vegetarian这个布尔值决定了菜肴是否为蔬菜,我们希望从这个集合中找到所有的蔬菜并返回一个list。

此时,我们就可以使用filter,它要求传入一个表达式,最终返回一个布尔值,所以我们直接将DishisVegetarian传入,如果是蔬菜则返回true,进入下一个流水线操作,反之则直接淘汰这个元素:

public static void main(String[] args) {
        List<Dish> vegetarianMenu =
                menu.stream()
                        //使用filter 结合函数式编程筛选出vegetarian 为true的菜肴
                        .filter(Dish::isVegetarian)
                        //将这些流组成一个list数组
                        .collect(toList());
        //遍历vegetarianMenu
        vegetarianMenu.forEach(System.out::println);

    }

最终输出结果如下,符合预期:

french fries
rice
season fruit
pizza

这种写法写起来就像SQL语句一样,我们无需各种for循环的声明指令,而是像是一种声明式的操作,而流的工作原理也如下图所示,将每一个元素放到流式操作的流水线上,符合预期的存入list,不符合预期的淘汰:

在这里插入图片描述

找出不重复元素

我们现在有一个无序且包含重复元素的整型数组,代码如下所示,希望能从中筛选出能够被2整除的数字并构成一个list集合:

  List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);

java8之前,你的编码思路可能会是:

  1. for循环找到被2整除的元素。
  2. 将该元素存到set中。
  3. 将set转转为list。

java8之后我们无需这么繁琐,我们只需针对流进行如下操作:

  1. 拿到集合流。
  2. 使用filter过滤出被2整除的元素,传到流水线下一步工序。
  3. 使用distinct判断是否重复。
  4. 存入list中。

对应代码如下:

public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        List<Integer> integerList = numbers.stream()
                //过滤出能够被2整除的数字
                .filter(i -> i % 2 == 0)
                //去重
                .distinct()
                //循环遍历
                .collect(Collectors.toList());
		//遍历输出结果
        for (Integer integer : integerList) {
            System.out.println(integer);
        }

    }

查看其输出结果,也是符合预期的:

2
4

再来看看流的工作图,他的操作也同样如流水线一般,我们这里就以数字1和数字2为例讲解一下流的工作过程:

  1. 流拿到数字1,走到filter表达式,返回false,直接淘汰。
  2. 流拿到数字2,走到filter表达式,返回true,走到下一个操作。
  3. 数字2执行distinct,不重复,进入下一个操作。
  4. 数字2存入list中。
  5. 流再次拿到数字2,走到filter表达式,返回true,走到下一个操作。
  6. 数字2执行distinct,重复,直接淘汰。

总的来说,流水编程之所以高效是因为它的流水线对于不符合要求的元素会直接过滤,相对于指令时的按部就班进行简洁许多:

在这里插入图片描述

限制筛选元素

以上文的菜肴集合为例,我们希望找到热量大于300卡的前3道菜,如果在java8之前,你一定的for循环加上一个count变量,当找到三道菜了就停止循环。
java8提供了语义化的操作limit方法,我们只需通过filter找到大于300卡的菜肴后,直接使用limit就可以完成限制筛选了

public static void main(String[] args) {
        List<Dish> menuList = menu.stream()
                //过滤出300卡的菜肴
                        .filter(d -> d.getCalories() > 300)
                //筛选出最先3个符合预期的菜肴
                        .limit(3)
                        .collect(toList());

        for (Dish dish : menuList) {
            System.out.println(dish);
        }

    }

对应的输出结果如下,符合预期:

pork
beef
chicken

跳过某些元素进行筛选

我们希望跳过前两个高于300卡的菜,再筛选出3道高于300卡的菜肴又该怎么办呢?对于java8而言,只需加一个skip操作即可完成这个需求:

public static void main(String[] args) {
        List<Dish> menuList = menu.stream()
                //过滤出300卡的菜肴
                        .filter(d -> d.getCalories() > 300)
                //跳过前两道热量高于300卡的菜
                .skip(2)
                //筛选出最先3个符合预期的菜肴
                        .limit(3)
                        .collect(toList());

        for (Dish dish : menuList) {
            System.out.println(dish);
        }

    }

从输出结果来看,确实高于300卡的前两个被剔除,然后再筛选出前3个元素:

chicken
french fries
rice

对应的原理图如下所示,可以看到经过filter表达式后,前两个高于300卡的元素直接被剔除:

在这里插入图片描述

映射

映射转换

映射操作其实也很好理解,就像使用sql语句一样通过select出你所需要的字段,例如我们希望从菜肴中拿到所有菜肴的名字,如果在java8之前,你一定会声明一个List<String>的临时集合,然后遍历菜肴集合,获取到每个菜肴的名字,添加到List<String>这个集合中。

java8直接基于map方法即可映射出自己所需要的成员属性,结合终端操作collect(toList())即可直接将映射结果转为list,避免了用户创建临时集合等繁琐操作:

public static void main(String[] args) {
        List<String> dishNames = menu.stream()
                //拿到每一个菜肴的名字
                .map(Dish::getName)
                //存入list集合中
                .collect(toList());

        for (String dishName : dishNames) {
            System.out.println(dishName);
        }


    }

输出结果:

pork
beef
chicken
french fries
rice
season fruit
pizza
prawns
salmon

映射扁平化

我们有 List<String> 的单词数组,我们希望找出数组中所有不重复的字母并输出,对应的单词数组定义如下:

 List<String> words = Arrays.asList("Hello", "World");

这时候你第一时间可能想到这样,将数组中每个单词切成一个个字母,然后distinct去重,最后转成list输出

public static void main(String[] args) {
        List<String> words = Arrays.asList("Hello", "World");


        List<String[]> resultList = words.stream()
                //这里映射的是stream<String[]> 后续的中间操作没有什么作用
                .map(w -> w.split(""))
                .distinct()
                .collect(toList());

        for (String[] strings : resultList) {
            for (String string : strings) {
                System.out.print(string);
            }
            System.out.println();
        }



    }

可以看到,这样的做法,最终得到的是一个 List<String[]>,代码如下,其工作原理也很好解释,map(w -> w.split(""))会将hello World分别切割成String[],然后两个String[],很显然对一个数组distinct自然是没有任何作用的:

在这里插入图片描述

打印以下输出结果

Hello
World

所以我们希望map操作后的数组转为Stringstream流,于是我们就有了第2个版本的写法,我们通过map(Arrays::stream),意将切割后的string[]转为Stream<String>再进行去重:

public static void main(String[] args) {
        List<String> words = Arrays.asList("Hello", "World");

        List<Stream<String>> list = words.stream()
                .map(w -> w.split(""))
                //将stream<String[]>转为stream<String> 但还是没有解决问题 因为将数组变成string流
                .map(Arrays::stream)
                .distinct()
                .collect(toList());

        for (Stream<String> stream : list) {
            List<String> stringList = stream.collect(Collectors.toList());
            for (String s : stringList) {
                System.out.print(s);
            }

            System.out.println();
        }


    }

,但是去重再转为数组后得到类型却是 List<Stream<String>>,这意味着我们只是将两个单词转为两个独立的stream<String>

在这里插入图片描述

所以我们需要更进一步的操作,来看看正确的写法,通过flatMap调用Arrays::stream,即可完成将两个独立的Stream<String>合并成一个扁平的Stream<String>最终得到正确结果,他的工作流程图也如下图所示

public static void main(String[] args) {
        List<String> words = Arrays.asList("Hello", "World");

        List<String> wordList = words.stream()
                .map(w -> w.split(""))
                //将数组扁平化合并为流
                .flatMap(Arrays::stream)
                .distinct()
                .collect(toList());

        for (String s : wordList) {
            System.out.println(s);
        }


    }

在这里插入图片描述

最终输出结果如下,符合预期:

H e l o W r d 

需要补充的是,对于扁平化的代码我们可以简化,我们可以直接通过表达式拿到集合中的元素在进行切割、扁平化操作:

  words.stream()
                 .flatMap((String line) -> Arrays.stream(line.split("")))
                 .distinct()
                 .forEach(System.out::println);

查找和匹配

检查是否至少匹配一个元素

我想知道菜肴集合中是否存在素菜,就可以使用anyMatch方法,该方法是一个终端操作,他将返回一个boolean值,只要集合中看到一个素食的菜肴,那么这样流操作就会返回true

public static void main(String[] args) {
        System.out.println(menu.stream().anyMatch(Dish::isVegetarian));
    }

输出结果:

true

通过peek方法查看anyMatch工作流程:

public static void main(String[] args) {
        menu.stream()
                .peek(m -> System.out.println(m))
                .anyMatch(Dish::isVegetarian);

    }

peek的输出结果来看,anyMatch只要匹配到符合要求的元素之后,就立即停止并关闭流了:

pork
beef
chicken
french fries

anyMatch的工作流程:

在这里插入图片描述

检查流元素是否都匹配

同理如果需要全部匹配,我们就用allMatch,例如我们需要判断菜肴中的菜肴是否都是低于1000卡的,我们完全可以这样写:

        menu.stream()
        	.allMatch(d -> d.getCalories() < 1000);

检查流元素是否都不都匹配

反过来来说,我们可以要找低于1000卡的,同样我们也可以使用下面这样的写法,判断是否不包含高于1000卡的菜肴

        menu.stream()
        	.noneMatch(d -> d.getCalories() >= 1000);

查找元素

我们希望找出菜肴中是否包含素食,如果有则告知查到的素食是什么菜,我们就可以通过使用findAny方法做到这一点:

public static void main(String[] args) {
        Optional<Dish> optionalDish = menu.stream()
                .filter(Dish::isVegetarian)
                //只要找到符合要求的菜肴,就直接停止并关闭流
                .findAny();

        //如果可以找到符合要求的元素,则直接输出打印
        if (optionalDish.isPresent()){
            System.out.println(optionalDish.get());
        }


    }

但是细心的读者看到了返回值竟然不是Dish而是Optional<Dish>,所以我们需要补充以下Optional的相关概念:

  1. Optional有个isPresent()方法,就以本例来说,假如集合中包含素食,我们调用这个方法就会返回true,说明找到了素食,反之返回false
  2. get()方法,以本示例来说,假如找到了素食,get就会返回菜肴对象,若没找到则报出NoSuchElement异常
  3. orElse()相比上一个方法更加友好,假如我们找到值就返回值,反之就返回orElse传入的参数值。

输出结果:

french fries

查找第一个元素

相比于查找元素,查找第一个元素语义化更加明显,例如我们想找到第一道素食,我们就可以使用findFirst,实际上关于findAnyfindFirst的使用场景区别不大,但是在并行的情况下,你想找到第一道素食的话,建议你使用findFirst,反之使用findAny即可,因为它使用并行流来说限制较少一些:

 public static void main(String[] args) {
        Optional<Dish> optionalDish = menu.stream()
                .filter(Dish::isVegetarian)
                //只要找到符合要求的菜肴,就直接停止并关闭流
                .findFirst();

        //如果可以找到符合要求的元素,则直接输出打印
        if (optionalDish.isPresent()){
            System.out.println(optionalDish.get());
        }


    }

规约

元素求和

java8之前,元素求和计算都需要经过这三步:

  1. 创建sum变量。
  2. 遍历集合,取出集合元素。
  3. 元素就和。

java8之后我们只需使用reduce结合求和表达式即可实现元素求和:

public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(4, 5, 3, 9);
        //起始数字为0,将列表中的元素全部累加
        int res = numbers.stream()
                .reduce(0, (sum, num) ->sum+num);
        //输出结果
        System.out.println(res);

    }

输出结果如下:

21

其工作原理如下图所示,即以我们传入的identity作为起始值,遍历列表中的每个数字与其进行累加:

在这里插入图片描述

基于上述代码我们使用Integer内置的一个相加的方法sum,于是代码就可以简化成下面这样:

public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(4, 5, 3, 9);
        //起始数字为0,将列表中的元素全部累加
        int res = numbers.stream()
                .reduce(0, Integer::sum);
        //输出结果
        System.out.println(res);

    }

假如你的统计操作无需初始值的话,也可以像下文这种写法,这正是java8的高明之处,返回一个Optional操作,让你有余地进行判空操作

·//无需初始值
        Optional<Integer> res = numbers.stream().reduce(Integer::sum);
        System.out.println(res.get());

求最大值和最小值

最大值和最小值做法和上文差不多,同样是基于reduce结合最大值或者最小值方法即可:

		//求最大值
		int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
        System.out.println(max);
		//求最最小值
        Optional<Integer> min = numbers.stream().reduce(Integer::min);
        min.ifPresent(System.out::println);

实践题

就以博客最早提到的菜肴类,我们希望用流式编程统计出菜肴的数量,可以看到笔者的做法很巧妙,通过映射将每道菜计算为1,传到reduce流中统计计算

 Optional<Integer> menuCount = menu.stream()
                .map(d -> 1)
                .reduce(Integer::sum);
        System.out.println(menuCount.get());

我们甚至可以简写成这样,因为java8为我们提供了这样的终端操作

 long count = menu.stream().count();
        System.out.println(count);

实践

需求描述

我们首先定义一个交易员的类,该类描述了交易员的姓名和居住城市:

public class Trader {

    /**
     * 姓名
     */
    private String name;
    /**
     * 居住城市
     */
    private String city;

    public Trader(String n, String c) {
        this.name = n;
        this.city = c;
    }

    public String getName() {
        return this.name;
    }

    public String getCity() {
        return this.city;
    }

    public void setCity(String newCity) {
        this.city = newCity;
    }

    public String toString() {
        return "Trader:" + this.name + " in " + this.city;
    }
}

还有一个交易订单类,它描述了订单的交易年份、交以金额、和交易这笔订单的人员:

public class Transaction{

    /**
     * 交易员
     */
    private Trader trader;
    /**
     * 交易年份
     */
    private int year;
    /**
     * 交以金额
     */
    private int value;

    public Transaction(Trader trader, int year, int value)
    {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }

    public Trader getTrader(){
        return this.trader;
    }

    public int getYear(){
        return this.year;
    }

    public int getValue(){
        return this.value;
    }

    public String toString(){
        return "{" + this.trader + ", " +
                "year: "+this.year+", " +
                "value:" + this.value +"}";
    }
}

用这两个类,构成了一个关于订单的列表:

		//4个交易员
 		Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario", "Milan");
        Trader alan = new Trader("Alan", "Cambridge");
        Trader brian = new Trader("Brian", "Cambridge");

		//4个交易员的订单总表
        List<Transaction> transactions = Arrays.asList(
                new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );

问题

基于上述代码,我们给出下面几道问题:

(1) 找出2011年发生的所有交易,并按交易额排序(从低到高)。
(2) 交易员都在哪些不同的城市工作过?
(3) 查找所有来自于剑桥的交易员,并按姓名排序。
(4) 返回所有交易员的姓名字符串,按字母顺序排序。
(5) 有没有交易员是在米兰工作的?
(6) 打印生活在剑桥的交易员的所有交易额。
(7) 所有交易中,最高的交易额是多少?
(8) 找到交易额最小的交易。

对应答案

上述8个问题笔者都已给出答案,读者在练习完成后可自行核对:

问题1:

        List<Transaction> tr2011 = transactions.stream()
                .filter(transaction -> transaction.getYear() == 2011)
                .sorted(comparing(Transaction::getValue))
                .collect(toList());
        System.out.println(tr2011);
        //找出2011年发生的所有交易,并按交易额排序(从低到高)
        List<Transaction> transactions_2011 = transactions.stream()
                .filter(t -> t.getYear() == 2011)
                .sorted(comparing(Transaction::getValue))
                .collect(toList());
        System.out.println(transactions_2011);

问题2:

        List<String> cities =
                transactions.stream()
                        .map(transaction -> transaction.getTrader().getCity())
                        .distinct()
                        .collect(toList());
        System.out.println(cities);

        //交易员都在哪些不同的城市工作过
        List<String> citys = transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getCity)
                .distinct()
                .collect(toList());
        System.out.println(citys);

问题3:


        List<Trader> traders =
                transactions.stream()
                        .map(Transaction::getTrader)
                        .filter(trader -> trader.getCity().equals("Cambridge"))
                        .distinct()
                        .sorted(comparing(Trader::getName))
                        .collect(toList());
        System.out.println(traders);

        //查找所有来自于剑桥的交易员,并按姓名排序
        List<Trader> cambridgeTraders = transactions.stream()
                .map(Transaction::getTrader)
                .filter(t -> "Cambridge".equals(t.getCity()))
                .distinct()
                .sorted(comparing(Trader::getName))
                .collect(toList());
        System.out.println(cambridgeTraders);

问题4:


        String traderStr =
                transactions.stream()
                        .map(transaction -> transaction.getTrader().getName())
                        .distinct()
                        .sorted()
                        .reduce("", (n1, n2) -> n1 + n2);
        System.out.println(traderStr);

        //返回所有交易员的姓名字符串,按字母顺序排序。×
        String names = transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getName)
                .distinct()
                .sorted()
                .reduce("", (s1, s2) -> s1 + s2);

        System.out.println(names);

问题5:


        boolean milanBased =
                transactions.stream()
                        .anyMatch(transaction -> transaction.getTrader()
                                .getCity()
                                .equals("Milan")
                        );
        System.out.println(milanBased);

        //(5) 有没有交易员是在米兰工作的? 
        boolean hasMilan = transactions.stream()
                .anyMatch(t -> "Milan".equals(t.getTrader().getCity()));

问题6:

        transactions.stream()
                .map(Transaction::getTrader)
                .filter(trader -> trader.getCity().equals("Milan"))
                .forEach(trader -> trader.setCity("Cambridge"));
        System.out.println(transactions);
        //(6) 打印生活在剑桥的交易员的所有交易额。
        Optional<Integer> sum = transactions.stream()
                .filter(t -> "Cambridge".equals(t.getTrader().getCity()))
                .map(Transaction::getValue)
                .reduce(Integer::sum);
        System.out.println(sum.get());

问题7:

        int highestValue =
                transactions.stream()
                        .map(Transaction::getValue)
                        .reduce(0, Integer::max);
        System.out.println(highestValue);


        //(7) 所有交易中,最高的交易额是多少?
        Optional<Integer> max = transactions.stream()
                .map(Transaction::getValue)
                .reduce(Integer::max);
        System.out.println(max.get());

问题8:


        Optional<Transaction> min2 = transactions.stream()
                .reduce((t1, t2) -> t1.getValue() < t2.getValue() ? t1 : t2);
        Optional<Transaction> min3 = transactions.stream()
                .min(comparing(Transaction::getValue));


        System.out.println(min +" "+ min2 +" " +min3);

参考文献

Java 8实战:https://book.douban.com/subject/25912747/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1299437.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BUUCTF crypto做题记录(3)新手向

目录 一、Rabbit 二、篱笆墙的影子 三、丢失的MD5 四、Alice与Bob 一、Rabbit 得到的密文&#xff1a;U2FsdGVkX1/ydnDPowGbjjJXhZxm2MP2AgI 依旧是看不懂是什么编码&#xff0c;上网搜索&#xff0c;在侧栏发现Rabbit解码&#xff0c;直接搜索就能有在线解码网站 二、篱笆…

【Vue第3章】使用Vue脚手架_Vue2

目录 3.1 初始化脚手架 3.1.1 说明 3.1.2 具体步骤 3.1.3 模板项目的结构 3.1.4 笔记与代码 3.1.4.1 笔记 3.1.4.2 01_src_分析脚手架 3.2 ref与props 3.2.1 ref 3.2.2 props 3.2.3 笔记与代码 3.2.3.1 笔记 3.2.3.2 02_src_ref属性 3.2.3.3 03_src_props配置 3…

【Linux】:线程(二)互斥

互斥与同步 一.线程的局部存储二.线程的分离三.互斥1.一些概念2.上锁3.锁的原理4.死锁 一.线程的局部存储 例子 可以看到全局变量是所有线程共享的&#xff0c;如果我们想要每个线程都单独访问g_val怎么办呢&#xff1f;其实我们可以在它前面加上__thread修饰。 这就相当于把g…

Java面向对象实践小结(含面试题)

继承 作用 提高了代码的复用性。让类与类之间产生了关系。有了这个关系&#xff0c;才有了多态的特性。 代码示范 父类代码 public class Parent {public void say() {System.out.println("父类的say方法");} }子类代码&#xff0c;继承父类&#xff0c;也就拥有…

如何确认网站是否有漏洞,如何找出网站存在的漏洞,找到漏洞该如何处理

如何确认网站或者服务器是否有漏洞 判断一个网站是否是存在漏洞的方法&#xff1a; 1.可以借助德迅云安全漏洞扫描功能来检查漏洞。 2.打开德迅云安全首页&#xff0c;点击最上面导航栏中的“安全产品”。 3.滑到“漏洞扫描”&#xff0c;选择“产品价格”服务。 4.选择您需…

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解前言DenseNet讲解Dense Block(稠密块)Dense Layer(稠密层)Transition Layer 过渡层DenseNet模型结构 DenseNet Pytorch代码完整代码附加…

DM8/达梦 数据库管理员使用手册详解

1.1DM客户端存放位置 Windows&#xff1a;DM数据库安装目录中tool文件夹和bin文件夹中。 Linux&#xff1a;DM数据库安装目录中tool目录和bin目录中。 1.2DM数据库配置助手 1.2.1Windows创建数据库 打开数据库配置助手dbca 点击创建数据库实例 选择一般用途 浏览选择数据库…

【基于大数据的人肥胖程度预测分析与可控策略】

基于大数据的人肥胖程度预测分析与可控策略 前言数据获取与清洗数据挖掘与分类建模1. K-means聚类2. 层次聚类3. DBSCAN4. 分类建模 数据可视化模型肥胖程度预测分析与可控策略结语 前言 随着现代生活方式的改变&#xff0c;肥胖问题逐渐成为全球性的健康挑战。为了更好地理解…

湖科大计网:计算机网络概述

一、计算机网络的性能指标 一、速率 有时候数据量也认为是以10为底的&#xff0c;看怎么好算。&#xff08;具体吉大考试用什么待商榷&#xff09; 二、带宽 在模拟信号系统中带宽的含义&#xff0c;本课程中用到的地方是&#xff1a;香农定理和奈奎斯特定理公式的应用之中。 …

未用的引脚如何处理?--持续更新中

前言&#xff1a; 随着集成电路规模的越来越大&#xff0c;如今的大规模芯片都集成了很多功能模块&#xff0c;但是在实际的电路设计中我们又不可能把芯片所有的功能模块(或者说接口)全部用上&#xff0c;因此总会有或多或少的管脚会“用不上”&#xff0c;那这些未用的管脚一般…

maven上传jar包到代码仓库

一、前言 一般被引用的包开发都是要求放在nexus仓库中&#xff0c;等到有jar包服务需要引用该包的时候直接从nexus仓库中获取即可&#xff0c;实现了该引用包的公用 二、代码配置 编辑代码中的pom.xml文件配置 vi pom.xml <distributionManagement><repository>&…

网络安全行业大模型调研总结

随着人工智能技术的发展&#xff0c;安全行业大模型SecLLM&#xff08;security Large Language Model&#xff09;应运而生&#xff0c;可应用于代码漏洞挖掘、安全智能问答、多源情报整合、勒索情报挖掘、安全评估、安全事件研判等场景。 本文首先介绍汇总了安全行业的大模型…

Java、JDK、JRE、JVM

Java、JDK、JRE、JVM 一、 Java 广义上看&#xff0c;Kotlin、JRuby等运行于Java虚拟机上的编程语言以及相关的程序都属于Java体系的一员。从传统意义上看&#xff0c;Java社区规定的Java技术体系包括以下几个部分&#xff1a; Java程序设计语言各种硬件平台上的Java虚拟机实…

Linux 进程终止

引入 在写 C 语言程序的时候&#xff0c;我们必写的结构就是&#xff1a; int main() {return 0; }在学习 C 语言的时候&#xff0c;我们好像并没有讨论过这个 return 0 有什么用&#xff0c;是干什么的&#xff01;return 1 可以吗&#xff1f;return 的返回值给谁看&#x…

英伟达危机大爆发!一夜之间,四面楚歌

今年以来&#xff0c;AI大模型明争暗斗、百花齐放。 但不管各种大模型打的有多厉害&#xff0c;很多人都认为“卖铲子”的英伟达才是最大赢家。 看一下英伟达今年的股票就知道英伟达赚的是多么盆满钵满。 英伟达CEO黄仁勋在发布 H200显卡时&#xff0c;应该是今年最意气风发的…

Swagger2的使用

手写Api文档的几个痛点&#xff1a; 文档需要更新的时候&#xff0c;需要再次发送一份给前端&#xff0c;也就是文档更新交流不及时。 接口返回结果不明确 不能直接在线测试接口&#xff0c;通常需要使用工具&#xff0c;比如postman 接口文档太多&#xff0c;不好管理 Sw…

Linux:进程优先级与命令行参数

目录 1.进程优先级 1.1 基本概念 1.2 查看系统进程 1.3 修改进程优先级的命令 2.进程间切换 2.1 相关概念 2.2 Linux2.6内核进程调度队列&#xff08;了解即可&#xff09; 3.命令行参数 1.进程优先级 1.1 基本概念 cpu资源分配的先后顺序&#xff0c;就是指进程的优…

探秘机器学习核心逻辑:梯度下降的迭代过程 (图文详解)

一 需求解函数 f() 和 g()函数分别为求y值和求导数的函数。 目的&#xff1a;求该函数的最小值&#xff1a; 代码&#xff1a; import numpy as np import matplotlib.pyplot as plt f lambda x : (x - 3.5) ** 2 - 4.5 * x 10 g lambda x : 2 * (x - 3.5) - 4.5x np.l…

class064 Dijkstra算法、分层图最短路【算法】

class064 Dijkstra算法、分层图最短路【算法】 算法讲解064【必备】Dijkstra算法、分层图最短路 code1 743. 网络延迟时间 // Dijkstra算法模版&#xff08;Leetcode&#xff09; // 网络延迟时间 // 有 n 个网络节点&#xff0c;标记为 1 到 n // 给你一个列表 times&…

一个或多个筛选器或者Listeners启动失败 的问题

核心&#xff1a; 这个就是有好多情况会导致这个问题&#xff0c;像是文件找不到&#xff0c;缺少jar包等原因&#xff0c;还是要看报错的具体信息。 报错情况&#xff1a; 一个或多个listeners启动失败&#xff0c;更多详细信息查看对应的容器日志文件 由于之前的错误&#x…