深入了解Java 8 新特性:Stream流的实践应用(一)

news2024/11/16 7:51:58

阅读建议

嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:

  1. 本篇文章大概一万多字,预计阅读时间长需要10分钟(不要害怕字数过多,其中有一大部分是示例代码,读起来是比较轻松的)。
  2. 本篇文章兼具实战性和理论性,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
  3. 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。

前言

        早就打算写一篇文章来梳理一下Java8的新特性Stream流的相关应用,终于得空来完成这件事了。原先以为这块内容应该不会太多,当我梳理完成以后,发现居然有两万多字。当然,在这两万字中,有一部分是示例代码。考虑到一口读完这两字,对于我的读者小伙伴来说,太不友好了,于是乎我打算,把这些内容拆成两部分:

        第一部分,主要是梳理Stream的核心方法;

        第二部分,主要是梳理Collectors类的核心方法;Collectors类是Stream实践应用中非常重要的一个工具类,读完这两篇文章相信肯定能意识到这一点。

Stream是什么

        Java的Stream是Java 8 引入的一个新特性,它提供了一种简洁、优雅的方式来处理集合数据。Stream允许你将集合中的元素进行过滤、映射、排序等操作,并将结果转换为一个新的集合。并且使用Stream,你可以将一个集合转换为一个流,然后对这个流进行各种操作,最后将结果收集到一个新的集合中。这种处理方式非常适合处理大量数据,因为它允许你在内存中一次只处理一个或一小批数据,而不是一次性加载整个数据集到内存中。因此Stream是java8新增特性中一个非常有用且强大的。它的核心特性:

  1. 声明性:Stream的操作以声明的方式进行,这使得代码更易读、易懂。声明性编程强调的是“做什么”,而不是“如何做”,这使得代码更具可维护性和可扩展性。
  2. 可复合:Stream的操作可以链式地进行,即可以将多个操作链接起来运行。这种可复合的特性使得对数据的处理更简洁、更易于理解。
  3. 可并行:Stream可以并行处理数据,这是为了适应多核机器的时代,提高系统CPU、内存的利用率。并行流是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。

这些特性的能够给你带来的好处是:

  1. 提高代码的可读性和可维护性:通过使用声明性和链式操作,可以让代码更加简洁、易于理解和维护。
  2. 提高系统的性能:通过并行流的处理方式,可以充分利用多核CPU的性能,提高系统的处理速度和性能。
  3. 适应大数据时代的需求:随着大数据时代的到来,对大量数据的处理成为一项重要的任务。Stream的并行流处理方式可以满足这种需求,提高数据处理的速度和效率。

Stream的核心方法

Stream#filter

        Stream#filter 方法用于根据指定的条件筛选出 Stream 中的元素。filter 方法接收一个 Predicate 参数,Predicate接口在Java中是一个函数式接口,它只有一个抽象方法,即test(T t),用于接受一个参数并返回一个布尔值。这个接口通常用于定义一个断言(即条件),在编程中可以用于对集合进行过滤或者在函数式编程中作为参数使用

        示例:

        使用Stream#filter()过滤出年龄等于18的学生信息

@Test
public void test() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    List<Student> targetList = list.stream().filter(item -> item.getAge() == 18).collect(Collectors.toList());
    for (Student student : targetList) {
        Assert.isTrue(student.getAge() == 18, "单元测试结果与预期不匹配");
    }
}

Stream#map

        Stream#map方法,它用于将 Stream 中的每个元素映射到另一个元素,Stream#map()方法接受一个Function类型的参数,而Function接口是Java 8引入的函数式接口,主要方法是apply(T t),它接受一个参数并返回一个结果。这个方法可以被看作是一个操作或者函数,它对输入进行某种处理并产生输出。

        示例:

        先使用Stream#filter()过滤出年龄大于18的学生信息,再使用Stream#map()方法把过滤到的结果信息映射成为另外一个类型的

@Test
public void test2() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    List<Person> targetList = list.stream()
            .filter(item -> item.getAge() > 18
            ).map(item -> new Person(item.getName(), item.getAge())).collect(Collectors.toList());
    Assert.notNull(targetList, "单元测试结果与预期不匹配");
}

Stream#mapToInt

        Stream.mapToInt()是Java8中Stream API 的一部分,mapToInt() 方法接受一个函数接口作为参数,可以用于将 Stream 中的元素映射为 int 类型,当调用 mapToInt() 方法时,Java 会遍历原始 Stream 中的每个元素,并将每个元素传递给指定的函数。然后,Java 会收集这些结果,最后返回返回一个 IntStream,在IntStream 上可以执行一些特殊的操作,如求和、统计、排序、最大值、最小值等

                示例:

  • 把学生信息中的年龄数据过滤到一个数组中
  • 统计所有学生信息的总年龄
  • 统计所有学生信息中的最大年龄
@Test
public void test3() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    //把学生信息中的年龄数据过滤到一个数组中
    int[] ageArr = list.stream().mapToInt(item -> item.getAge()).toArray();
    for (int age : ageArr) {
        System.out.println(age);
    }
    //统计所有学生信息的总年龄
    int sum = list.stream().mapToInt(item -> item.getAge()).sum();
    System.out.println(sum);
    //统计所有学生信息中的最大年龄
    Integer maxAge = list.stream().map(item -> item.getAge()).max((v1, v2) -> {
        if (v1 > v2) {
            return 1;
        } else if (v1 < v2) {
            return -1;
        }
        return 0;
    }).get();
    System.out.println(maxAge);
}

Stream#distinct

        Stream#distinct 方法用于去除 Stream 中的重复元素,它会返回由不同元素组成的新 Stream。这个方法实际上调用了 Object.equals(Object o) 方法,默认的行为是比较两个对象的引用是否相等。如果两个对象的引用相等,则认为它们相等;反之则认为它们不相等。因此,在使用 distinct 方法时,如果需要比较的元素是自定义对象,需要在自定义类中重写 equals() 和 hashCode() 方法。

        示例:

        给存在重复学生信息的集合进行去重操作并回收结果

@Test
public void test4() {
    //wangwu的信息存在重复
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17), new Student("wangwu", 17));
    List<Student> targetList = list.stream().distinct().collect(Collectors.toList());
    Assert.isTrue(list.size() > targetList.size(), "单元测试结果与预期不匹配");
}

Stream#sorted

        Stream#sorted 方法用于对 Stream 中的元素进行排序。它返回一个包含按指定排序规则排序后元素的新的 Stream,默认情况下,使用自然顺序排序(对于实现了 Comparable 的元素类型)。

        示例

  • 自然排序,默认是升序,这里是首字母升序
  • 自定义排序,lambda表达式定义排序逻辑,这里是降序
@Test
public void test5() {
    //自然排序,默认是升序,这里是首字母升序
    List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    List<String> sortedCopy = names.stream().sorted().collect(Collectors.toList());
    String str = sortedCopy.stream().collect(Collectors.joining(","));
    System.out.println(str); 
    //自定义排序,lambda表达式定义排序逻辑,这里是降序
    List<Integer> ages = Arrays.asList(18, 17, 19, 20);
    List<Integer> ages2 = ages.stream().sorted((v1, v2) -> {
        if (v1 > v2) {
            return -1;
        } else if (v1 < v2) {
            return 1;
        } else {
            return 0;
        }
    }).collect(Collectors.toList());
    System.out.println(ages2.toString());
}

Stream#peek

        Stream.peek() ,它为每个元素提供了一个消费函数。该方法返回由该流的元素组成的流,并对每个元素执行所提供的 Consumer 操作方法,Consumer接口是java8的一个函数式接口,它定义了一个名为 accept 的抽象方法,该方法接受一个参数并且不返回任何结果。peek() 方法主要用于调试,以便在元素流过管道中的某个点时查看它们。peek() 是一个中间操作方法,将在调用终端方法时执行。

        示例

        打印输出以z开头的姓名;

@Test
public void test6() {
    List<String> names = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    Stream<String> stream = names.stream()
            .peek(item -> {
                if (item.startsWith("z")) {
                    System.out.println(item);
                }
            });
    //在执行collect方法前,peek方法内的lambda表达式不会被执行;只有在终端方法collect()被调用时才会执行
    List<String> names2 = stream.collect(Collectors.toList());
    System.out.println(names2);
}

Stream#limit

        Stream#limit 方法用于限制 Stream 中元素的数量。它返回一个包含指定数量元素的新的 Stream,而不会改变原始 Stream 中的元素顺序。

        示例

        获取集合内的前两个元素

@Test
public void test7() {
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    List<String> result = list.stream().limit(2).collect(Collectors.toList());
    System.out.println(result.toString());
}

Stream#skip

        Stream#skip 方法,用于跳过 Stream 中的前 n 个元素。它返回一个新的 Stream,该 Stream 不包含原始 Stream 中的前 n 个元素。

        示例:

        跳过集合内的前3个元素,而获取剩余其他元素

@Test
public void test8() {
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    List<String> result = list.stream().skip(3).collect(Collectors.toList());
    System.out.println(result.toString());
}

Stream#forEach

        Stream#forEach 方法,用于对 Stream 中的每个元素执行遍历操作。该方法没有返回值,它只会对 Stream 中的每个元素进行遍历操作,而不会改变 Stream 中的元素或产生新的结果。

示例

@Test
public void test9() {
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    list.stream().forEach(item-> System.out.println(item));
}

Stream#forEachOrdered

        Stream#forEachOrdered方法 ,用于对 Stream 中的每个元素按照它们在 Stream 中的顺序执行一个提供的操作。与 Stream#forEach 方法不同的是,forEachOrdered方法 会保证操作的顺序与 Stream 中元素的顺序一致,而Stream#forEach方法则不保证操作的顺序。

        示例

@Test
public void test10() {
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    list.stream().forEachOrdered(item-> System.out.println(item));
}

Stream#reduce

        Stream#reduce 方法,用于将 Stream 中的元素进行某种聚合操作,并返回一个单一的结果。它接受一个 BinaryOperator 作为参数,该操作接受两个参数并返回一个结果。在聚合过程中,每个元素都会与前一个元素进行操作,并将结果传递给下一个元素,直到处理完所有元素并返回最终结果。使用 Stream#reduce 方法可以对数据进行求和、求积、求最大值、求最小值等各种聚合操作

        示例:

        求集合内所有学生信息中的学生年龄之和

@Test
public void test11() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    Integer totalAge = list.stream().reduce((val1, val2) -> new Student(val1.getAge() + val2.getAge())).get().getAge();
    System.out.println(totalAge);
}

Stream#collect

        Stream#collect 方法,用于将 Stream 中的元素收集到集合或其他对象中,如 List、Set、Map 等。它接受一个 Collector 作为参数,该 Collector 是一个函数式接口,用于定义将元素收集到目标集合或其他对象中的操作。

        关于Collector,可以参考Collectors类,该类内置很多静态方法,用于获取常见的Collector;

Stream#min

        Stream#min方法,用于找到 Stream 中元素的最小值。它返回 Stream 中元素的最小值,如果 Stream 为空,则返回 Optional.empty。Stream#min方法接受一个比较器作为参数,可以根据特定的业务逻辑或数据类型自定义自己的比较逻辑。

        示例

        获取集合内年龄最大的学生信息

    @Test
    public void test12() {
        List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
        Student student = list.stream().min((v1, v2) -> {
            if (v1.getAge() > v2.getAge()) {
                return 1;
            } else if (v1.getAge() < v2.getAge()) {
                return -1;
            } else {
                return 0;
            }
        }).get();
        System.out.println(student.toString());
    }
}

Stream#max

        与Stream#min方法类似,Stream#max用于找到 Stream 中元素的最大值,Stream#max方法接受一个比较器作为参数,可以根据特定的业务逻辑或数据类型自定义自己的比较逻辑。

@Test
public void test13() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    Student student = list.stream().max((v1, v2) -> {
        if (v1.getAge() > v2.getAge()) {
            return -1;
        } else if (v1.getAge() < v2.getAge()) {
            return 1;
        } else {
            return 0;
        }
    }).get();
    System.out.println(student.toString());
}

Stream#count

        Stream#count方法的功能是计算Stream中元素的数量,并返回一个long类型的数值。这个方法不会将Stream中的所有元素收集到一个集合中,而是直接在流上执行计数操作,因此可以高效地计算出Stream中元素的数量。单纯使用count(),与size()效果是一样的,实际使用过程中,一般会结合其他中间方法使用,如filter();

        示例

        统计姓名集合中以z开头的元素有几个

@Test
public void test14() {
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    long num = list.stream().filter(item -> item.startsWith("z")).count();
    System.out.println(num);
}

Stream#anyMatch

        Stream#anyMatch 方法,用于判断 Stream 中的元素是否满足指定的匹配条件。如果 Stream 中至少有一个元素满足匹配条件,则返回 true;否则返回 false。

        示例

        统计学生信息集合中,是否存在有年龄小于18的学生信息

@Test
public void test15() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    boolean flag = list.stream().anyMatch(item -> item.getAge() < 18);
    System.out.println(flag);//结果是true
}

Stream#allMatch

        Stream#allMatch 方法用于检查 Stream 中的所有元素是否满足给定的条件函数。如果 Stream 中的所有元素都满足条件函数,则返回 true,否则返回 false,可以用在需要检查 Stream 中所有元素是否满足某个条件的场景中。

        示例

        检查学生集合集合中的学生年龄是否全部大于18

@Test
public void test16() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    boolean flag = list.stream().allMatch(item -> item.getAge() < 18);
    System.out.println(flag);//结果是false
}

Stream#noneMatch

        Stream#noneMatch方法,它用于检查Stream中的元素是否都不满足给定的断言条件。Stream#noneMatch方法接受一个Predicate(断言)作为参数,该断言用于测试每个元素是否满足某个条件。如果Stream中没有任何一个元素满足断言条件,则noneMatch方法返回true;否则返回false。

        示例

        检查学生信息集合中的学生姓名首字母是否都不是以a开头

@Test
public void test17() {
    List<Student> list = Arrays.asList(new Student("zhangsan", 18), new Student("lisi", 19), new Student("wangwu", 17));
    boolean flag = list.stream().noneMatch(item -> item.getName().startsWith("a"));
    System.out.println(flag);//结果是
}

Stream#findFirst

        Stream#findFirst 方法,用于查找并返回 Stream 中的第一个元素。使用 findFirst 方法可以方便地查找符合特定条件的第一个元素,而无需遍历整个 Stream。findFirst 方法不会在 Stream 为空时抛出异常,而是返回一个空的 Optional 对象。可以结合着filter方法一起使用。

        示例

        检索出学生姓名集合中学生姓名以z开头的第一个姓名

@Test
public void test18() {
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    String name = list.stream().filter(item->item.startsWith("w")).findFirst().get();
    System.out.println(name);//结果是wangwu
}

Stream#findAny

        在 Java 11 中,Stream.findAny() 方法用于在流中查找满足特定条件的第一个元素。这个方法返回一个 Optional 对象,表示可能的元素。如果流为空,则返回一个空的 Optional。

        示例

@Test
public void test19(){
    List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");
    String name = list.stream().findAny().get();
    System.out.println(name); //结果为zhangsan
    List<String> list2=new ArrayList<>();
    boolean flag = list2.stream().findAny().isEmpty();
    System.out.println(flag);//结果为true
}

Stream#of

        Stream#of() 方法,用于创建一个包含指定元素的 Stream。这个方法接收一个可迭代的数据源,如数组或集合,并返回一个包含该数据源中所有元素的 Stream。

        示例

@Test
public void test20(){
    long count = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu").count();
    System.out.println(count);
}

Stream#iterator

        Stream#iterator 方法,用于获取一个迭代器,用于遍历 Stream 中的元素。这个方法返回一个 Iterator 对象,可以使用 next() 方法依次获取 Stream 中的每个元素。

@Test
public void test21(){
    Iterator<String> iterator = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu").iterator();
    while (iterator.hasNext()){
        String next = iterator.next();
        System.out.println(next);
    }
}

下一篇:深入了解Java 8 新特性:Stream流的实践应用(二) 

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

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

相关文章

关于在3dsmax中制作的模型导入UE后尺寸大小不对的问题

现象 在3dsmax中的基本单位为毫米 在UE中基本单位是厘米 我在3dsmax中创建一个长宽高均为1000mm的方块 然后导入到UE中的世界坐标原点 方块向X轴正方向移动100个单位100cm1000mm&#xff0c;按理来说&#xff0c;新方块的此时应该和旧方块是贴着的&#xff0c;但是现象确是两者…

厦门城市内涝的落地解决方案,城市内涝积水监测系统

有来过厦门的都知道这是一座让人想要扎根的城市&#xff0c;但是这座城市在受2023年第11号台风“海葵”影响&#xff0c;9月份连续3天出现大暴雨天气&#xff0c;厦门受强降水影响&#xff0c;全市共有积水点位24处&#xff0c;造成了极大的交通阻塞&#xff0c;却没有及时进行…

P9232 [蓝桥杯 2023 省 A] 更小的数(区间DP)

求大数字某连续部分反转后&#xff0c;比原数字小的个数 思路&#xff1a;自前向后遍历 ai是位于数字第i位的数字 aj是位于数字第j位的数字&#xff08;i<j&#xff09; ai>aj f[ai][aj]1; ai<aj f[ai][aj]0; aiaj f[ai][aj]f…

1688开放平台API接口获取商品详情信息

一、API接口简介 1688开放平台提供了丰富的API接口&#xff0c;帮助开发者快速实现各种业务需求。其中&#xff0c;商品详情信息的获取是很多业务场景中的基础功能。通过调用相应的API接口&#xff0c;您可以获取到商品的基本信息、价格、库存等数据&#xff0c;为您的业务提供…

【Android Jetpack】理解ViewModel

文章目录 ViewModel实现ViewModelViewModel的生命周期在Fragments间分享数据ViewModel和SavedInstanceState对比ViewModel原理ViewModel与AndroidViewModel ViewModel Android系统提供控件&#xff0c;比如Activity和Fragment&#xff0c;这些控件都是具有生命周期方法&#x…

鸿蒙系统扫盲(二):再谈鸿蒙是不是安卓套壳?

最近小米发布了澎湃OS&#xff0c;vivo发布了蓝OS&#xff0c;好像自从华为回归后&#xff0c;大伙都开始写自己的OS了&#xff0c;小米官方承认是套壳安卓&#xff0c;然后被大家喷了&#xff0c;于是鸿蒙是不是安卓套壳的话题又回到了大众的视野&#xff0c;今天在讨论下这个…

HarmonyOS ArkTS开发语言介绍(三)

1 引言 Mozilla创造了JS&#xff0c;Microsoft创建了TS&#xff0c;Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力&#xff0c;到具备类型系统的高效工程开发能力&#xff0c;再到融合声明式UI、多维状态管理等丰富的应用开发能力&#xff0c;共同组成了相关的演进脉…

vue3 uniapp h5 安卓和iOS开发适配踩坑记录

font-size适配屏幕大小及iOS和安卓状态栏及安全距离的处理 App.vue <script setup lang"ts"> import { onLaunch, onShow, onHide } from "dcloudio/uni-app"; import ./main.scss onLaunch(() > {console.log("App Launch");var wid…

gitlab设置项目clone地址

直接在线修改地址 虽然是个小问题但是我查了很多都是说要去修改配置文件&#xff0c;可是我是docker部署的&#xff0c;修改配置文件之后我还要重新打包镜像想想都不咋规范&#xff0c;后才终于知道可以直接设置&#xff0c;不要改配置文件&#xff01;&#xff01;&#xff0…

亚马逊运营中动态/静态住宅IP代理的应用有哪些?跨境电商必备

作为全球最大的电商平台之一&#xff0c;亚马逊已经成为许多商家的首选销售平台。而代理IP作为近几天互联网的热门工具&#xff0c;在跨境电商界也起着非常强大的作用。那么在亚马逊运营中&#xff0c;适合动态住宅代理还是静态住宅代理呢&#xff1f;下面我们一起来探索&#…

C语言for循环实现斐波那契数列

斐波那契数列指的是这样一个数列 0,1, 1, 2, 3, 5, 8, 13, 21… 这个数列从第3项开始&#xff0c;每一项都等于前两项之和。 int main(){//前两项分别定义为i&#xff0c;j 两项之和我们定义为k//由于从第三项开始&#xff0c;所以先将前两项打印出来0和1int i0,j1,k;printf(&…

解决requests库进行爬虫ip请求时遇到的错误的方法

目录 一、超时错误 二、连接错误 三、拒绝服务错误 四、内容编码错误 五、HTTP错误 在利用requests库进行网络爬虫的IP请求时&#xff0c;我们可能会遇到各种错误&#xff0c;如超时、连接错误、拒绝服务等等。这些错误通常是由目标网站的限制、网络问题或我们的爬虫代码中…

手机照片一键去水印轻松摆脱不需要的旁观者

是什么让照片中的意外客人成为挑战&#xff1f;我们都经历过这种情况——在热门地标或繁忙的城市街道拍照&#xff0c;不可避免地会在画面中捕捉到陌生人。有时他们会无意中抢尽风头&#xff0c;转移观众的注意力。 这些水印不仅影响了照片的美观度&#xff0c;还给我们的观赏体…

【Element】el-progress 自定义进度条

一、背景 要求弹窗内显示进度条&#xff0c;根据接口获取当前进度值&#xff0c;间隔5秒调用接口获取最新进度值&#xff0c;当进度值为100时&#xff0c;允许关闭进度条弹窗 二、效果 三、实现步骤 3.1、按钮绑定事件&#xff0c;打开弹窗 <el-button class"cance…

dump备份命令

dump备份文件系统&#xff0c;或者目录 文件系统有等级划分&#xff0c;0为全部备份&#xff0c;1.针对上一次有变动的文件进行备份&#xff0c;以此类崔 目录备份&#xff1a;只有一个等级0&#xff0c; 针对文件系统类型有要求ext2&#xff0c;ext3&#xff0c;如果是其他…

(附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366

SSM多源异构数据关联技术构建智能校园 摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;高校当然也不能排除在外。多源异构数据关联技术构建的智能校园是以实际运用为开发…

养猫7年:猫罐头牌子哪个好用?5款口碑好的猫罐头推荐!

猫罐头牌子哪个好用&#xff1f;刚开始养猫真的好心累&#xff0c;因为一开始啥也不懂&#xff0c;关于猫猫的饮食这也不会选那也不会选&#xff0c;就很容易踩雷&#xff0c;为此花了不少钱&#xff0c;相信很多新手铲屎官现在也处于这种状态吧。 作为一个养猫7年的资深铲屎官…

高德地图点击搜索触发输入提示

减少调用次数&#xff0c;不用每输入一次调用一次&#xff0c;输入完后再触发搜索 效果图&#xff1a; ![Alt](https://img-home.csdnimg.cn/images/20220524100510.png dom结构 <div class"seach"><van-searchshow-actionv-model"addressVal"…

docker和docker-compose生产的容器,不在同一个网段,解决方式

在实际项目中&#xff0c;使用docker run xxXx 和docker-compose up -d 不在同一个网段&#xff0c;一个是默认是172.17.x.x, 另一个是172.19.x.x。为解决这个问题需要自定义一个网络&#xff0c;我命名为“my-bridge” 首先熟悉几条命令&#xff1a; docker network ls 或…

构建和应用卡尔曼滤波器 (KF)--扩展卡尔曼滤波器 (EKF)

作为一名数据科学家&#xff0c;我们偶尔会遇到需要对趋势进行建模以预测未来值的情况。虽然人们倾向于关注基于统计或机器学习的算法&#xff0c;但我在这里提出一个不同的选择&#xff1a;卡尔曼滤波器&#xff08;KF&#xff09;。 1960 年代初期&#xff0c;Rudolf E. Kal…