【Lambda】java之lambda表达式stream流式编程操作集合

java之lambda表达式&stream流式编程操作集合

  • 1 stream流概念
    • 1.1 中间操作
      • 1.1.1 无状态操作
      • 1.1.2 有状态操作
    • 1.2 终端操作
      • 1.2.1 非短路操作
      • 1.2.2 短路操作
  • 2 steam流的生成
    • 2.1 方式一:数组转为stream流
    • 2.2 方式二:集合转为steam流
    • 2.3 方式三:Stream.builder创建stream流
    • 2.4 方式四:使用 Stream.of 方法
    • 2.5 方式五:从文件创建流
    • 2.6 方式六:生成无限流
  • 3 无状态的中间操作
    • 3.1 distinct
    • 3.2 limit
    • 3.3 skip
    • 3.4 sorted
    • 3.5 组合使用
  • 4 有状态的中间操作
    • 4.1 filter(重要)
    • 4.2 map(重要)
    • 4.3 flatMap
    • 4.4 peek
    • 4.5 组合使用
  • 5 非短路的终端操作
    • 5.1 forEach
    • 5.2 toArray
    • 5.3 reduce(重要)
    • 5.4 collect(重要)
    • 5.5 min、max、count
    • 5.6 组合使用
  • 6 短路的终端操作
    • 6.1 anyMatch
    • 6.2 allMatch
    • 6.3 noneMatch
    • 6.4 findFirst
    • 6.5 findAny
    • 6.6 组合使用
  • 7 并行流
  • 8 总结

1 stream流概念

简单来讲,Stream流是一种用于处理数据集合的高级迭代器,它可以对集合中的元素进行各种操作,如过滤、映射、排序等。通过使用Stream API,我们可以以声明式的方式处理数据,而无需显式地编写循环和条件语句。
Stream流的操作分为两种,中间操作终端操作

1.1 中间操作

是指对每个元素独立进行操作,不依赖于其他元素的状态。它们不会改变流中的元素本身,而是创建一个新的Stream对象来表示转换后的结果。常见的无状态中间操作有map、filter、flatMap等。

1.1.1 无状态操作

无状态操作不会改变流中的元素,也不会改变流的状态;这些操作可以并行执行,因为它们不依赖于流中的其他元素。例如:

  • distinct:返回去重的Stream。
  • limit:限制从流中获得前n个数据,返回前n个元素数据组成的Stream流。
  • skip:跳过前n个数据,返回第n个元素后面数据组成的Stream。sorted:返回一个排序的Stream。

1.1.2 有状态操作

有状态操作会改变流的状态,或者依赖于流中的其他元素。这些操作不能并行执行,因为它们需要访问或修改流的状态。
例如:

  • filter:过滤流,过滤流中的元素,返回一个符合条件的Stream
  • map:转换流,将一种类型的流转换为另外一种流。(mapToInt、mapToLong、mapToDouble 返回int、long、double基本类型对应的Stream)
  • peek:主要用来查看流中元素的数据状态,该方法主要用于调试,方便debug查看Stream内进行处理的每个元素。仅在对流内元素进行操作时,peek才会被调用,当不对元素做任何操作时,peek自然也不会被调用了
  • flatMap:简单的说,就是一个或多个流合并成一个新流。

1.2 终端操作

是对数据进行最终处理的操作,它们会消耗掉Stream并产生一个结果或者副作用(如输出到控制台)。一旦执行了终端操作,Stream就不能再被使用。常见的终端操作有collect、forEach、reduce等。

1.2.1 非短路操作

非短路操作会处理流中的所有元素,并返回一个结果。
如:

  • forEach:循环操作Stream中数据。
  • toArray:返回流中元素对应的数组对象。
  • reduce:聚合操作,用来做统计,将流中元素反复结合起来统计计算,得到一个值.。
  • collect:聚合操作,封装目标数据,将流转换为其他形式接收,如:List、Set、Map、Array。
  • min、max、count:聚合操作,最小值,最大值,总数量。

1.2.2 短路操作

短路操作会在满足某个条件时提前结束处理,并返回一个结果。例如:

  • anyMatch:短路操作,有一个符合条件返回true。
  • allMatch:所有数据都符合条件返回true。
  • noneMatch:所有数据都不符合条件返回true。
  • findFirst:短路操作,获取第一个元素。
  • findAny:短路操作,获取任一元素。

2 steam流的生成

2.1 方式一:数组转为stream流

int [] arr = {1,2,3,4,5,6,7,8,9,10};       
Arrays.stream(arr).forEach(System.out::println);

2.2 方式二:集合转为steam流

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
list.stream().forEach(System.out::println);

2.3 方式三:Stream.builder创建stream流

Stream.builder创建stream流,允许你逐步构建一个流

Stream.Builder<Integer> builder = Stream.builder();

// 添加元素到流中
builder.add(1);
builder.add(2);
builder.add(3);

// 构建流
Stream<Integer> stream = builder.build();

// 使用流
stream.forEach(System.out::println);

2.4 方式四:使用 Stream.of 方法

Stream.of 方法可以接受一系列元素并返回一个包含这些元素的流。

Stream<String> words = Stream.of("apple", "banana", "orange");
words.forEach(System.out::println);

2.5 方式五:从文件创建流

可以使用 Files.lines 方法从文件中创建流。

try (Stream<String> stream = Files.lines(Paths.get("file.txt"))) {
    stream.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}

2.6 方式六:生成无限流

可以使用 Stream.generate 或 Stream.iterate 方法来生成无限流。

Stream<Double> randomNumbers = Stream.generate(Math::random);
randomNumbers.forEach(System.out::println);
Stream<Integer> oddNumbers = Stream.iterate(1, n -> n + 2);
oddNumbers.forEach(System.out::println);

3 无状态的中间操作

3.1 distinct

返回一个去重的流,即去除重复的元素

Stream<Integer> distinctStream = Stream.of(1, 2, 2, 3, 4, 4, 5).distinct();
distinctStream.forEach(System.out::println);
//输出结果:12345

3.2 limit

限制从流中获得前n个数据,返回前n个元素数据组成的流

Stream<Integer> limitedStream = Stream.of(1, 2, 3, 4, 5).limit(3);
limitedStream.forEach(System.out::println);
//输出结果:123

3.3 skip

Stream<Integer> skippedStream = Stream.of(1, 2, 3, 4, 5).skip(2);
skippedStream.forEach(System.out::println);
//输出结果:345

3.4 sorted

//正序排序从小到大
Stream<Integer> sortedStream = Stream.of(5, 3, 1, 4, 2).sorted();
sortedStream.forEach(System.out::println);
//输出结果:12345

//逆序排序从大到小,Comparator.reverseOrder() 创建了一个逆序比较器,然后传递给 sorted 方法,从而实现了逆序排序
Stream<Integer> sortedStream = Stream.of(5, 3, 1, 4, 2).sorted(Comparator.reverseOrder());
sortedStream.forEach(System.out::println);
//输出结果:54321

3.5 组合使用

这段代码首先去重,然后排序,跳过第一个元素,最后限制结果流只包含前三个元素

Stream<Integer> stream = Stream.of(1, 2, 2, 3, 4, 4, 5)
                .distinct()
                .sorted()
                .skip(1)
                .limit(3);
stream.forEach(System.out::println);
//输出结果:234

测试实体类:

@Data
public class Person {
    private int id;
    private String name; // 姓名
    private int salary; // 薪资
    private int age; // 年龄
    private String sex; //性别
    private String area; // 地区
    private List<Person> employeeList; //下属

    public Person() {
    }

    // 构造方法
    public Person(String name, int salary, int age,String sex,String area) {
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }

    // 构造方法
    public Person(int id, String name, int salary, int age, String sex, String area) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", area='" + area + '\'' +
                '}';
    }
}
// 创建一个List来存储Person对象
List<Person> personList = new ArrayList<>();

// 创建8个Person对象并添加到列表中
personList.add(new Person(1, "Alice", 5000, 30, "Female", "New York"));
personList.add(new Person(2, "Bob", 6000, 35, "Male", "Los Angeles"));
personList.add(new Person(3, "Charlie", 5500, 28, "Male", "Chicago"));
personList.add(new Person(4, "Diana", 7000, 40, "Female", "Miami"));
personList.add(new Person(5, "Ethan", 4800, 25, "Male", "Houston"));
personList.add(new Person(6, "Fiona", 5300, 32, "Female", "Seattle"));
personList.add(new Person(7, "George", 6200, 38, "Male", "Boston"));
personList.add(new Person(8, "Hannah", 5900, 29, "Female", "San Francisco"));

4 有状态的中间操作

4.1 filter(重要)

// 1. 筛选出所有女性
List<Person> females = personList.stream()
        .filter(person -> person.getSex().equalsIgnoreCase("female"))
        .collect(Collectors.toList());
System.out.println("女性列表: " + females);

// 2. 筛选出薪资高于5000的人员
List<Person> highSalary = personList.stream()
        .filter(person -> person.getSalary() > 5000)
        .collect(Collectors.toList());
System.out.println("薪资高于5000的人员: " + highSalary);

// 3. 筛选出年龄在30岁及以上的人员
List<Person> ageAbove30 = personList.stream()
        .filter(person -> person.getAge() >= 30)
        .collect(Collectors.toList());
System.out.println("年龄在30岁及以上的人员: " + ageAbove30);

// 4. 筛选出居住在特定城市(例如"New York")的人员
List<Person> livingInNewYork = personList.stream()
        .filter(person -> person.getArea().equalsIgnoreCase("New York"))
        .collect(Collectors.toList());
System.out.println("居住在纽约的人员: " + livingInNewYork);

// 5. 筛选出名字以"A"开头的人员
List<Person> namesStartingWithA = personList.stream()
        .filter(person -> person.getName().startsWith("A"))
        .collect(Collectors.toList());
System.out.println("名字以A开头的人员: " + namesStartingWithA);

4.2 map(重要)

// 1. 提取所有人的名字
List<String> names = personList.stream()
        .map(Person::getName)
        .collect(Collectors.toList());
System.out.println("所有人的名字: " + names);

// 2. 提取所有人的薪资
List<Integer> salaries = personList.stream()
        .map(Person::getSalary)
        .collect(Collectors.toList());
System.out.println("所有人的薪资: " + salaries);

// 3. 提取所有人的地区
List<String> cities = personList.stream()
        .map(Person::getArea)
        .collect(Collectors.toList());
System.out.println("所有人的城市: " + cities);

// 4. 提取所有人的年龄,并加上10
List<Integer> agesPlus10 = personList.stream()
        .map(person -> person.getAge() + 10)
        .collect(Collectors.toList());
System.out.println("所有人的年龄加十: " + agesPlus10);

// 5. 提取薪资信息并格式化为字符串
List<String> salaryInfo = personList.stream()
        .map(person -> person.getName() + "的薪资为: " + person.getSalary())
        .collect(Collectors.toList());
System.out.println("薪资信息: " + salaryInfo);

4.3 flatMap

flatMap 是 Java Stream API 中的一个非常有用的方法,通常用于将多个流扁平化为一个流。在处理 Person 对象时,我们可以使用 flatMap 来进行一些复杂的数据结构操作。以下是一些示例,展示如何在你的 personList 上使用 flatMap。

List<String> flatMappedList = personList.stream()
                                .map(person -> person.getName()) // 将Person对象转换为名字
                                .flatMap(name -> Stream.of(name, name.toUpperCase())) // 将名字转换为名字和名字的大写形式
                                .collect(Collectors.toList());

4.4 peek

personList.stream()
          .peek(person -> System.out.println("Before filter: " + person)) // 打印每个Person对象
          .filter(person -> person.getAge() > 30) // 过滤年龄大于30的Person对象
          .peek(person -> System.out.println("After filter: " + person)) // 打印过滤后的Person对象
          .collect(Collectors.toList());

4.5 组合使用

// 使用Stream API处理personList
List<String> combinedList = personList.stream()
                                      .filter(person -> person.getAge() > 30) // 过滤年龄大于30的Person对象
                                      .map(person -> person.getName()) // 将Person对象转换为名字
                                      .flatMap(name -> Stream.of(name, name.toUpperCase())) // 将名字转换为名字和名字的大写形式
                                      .peek(System.out::println) // 打印每个名字
                                      .collect(Collectors.toList()); // 收集结果到一个List中

5 非短路的终端操作

5.1 forEach

personList.stream()
          .forEach(person -> System.out.println(person.getName()));

personList.stream()
          .forEachOrdered(person -> System.out.println(person.getName()));

5.2 toArray

Object[] array = personList.stream().toArray();

5.3 reduce(重要)

// 1. 计算总薪资
int totalSalary = personList.stream()
        .map(Person::getSalary)
        .reduce(0, Integer::sum);
System.out.println("总薪资: " + totalSalary);

// 2. 计算平均薪资
Optional<Double> averageSalary = personList.stream()
        .map(Person::getSalary)
        .reduce((a, b) -> a + b)
        .map(sum -> sum / (double) personList.size());
System.out.println("平均薪资: " + averageSalary.orElse(0.0));

// 3. 查找最高薪资
Optional<Integer> maxSalary = personList.stream()
        .map(Person::getSalary)
        .reduce(Integer::max);
System.out.println("最高薪资: " + maxSalary.orElse(0));

// 4. 查找最低薪资
Optional<Integer> minSalary = personList.stream()
        .map(Person::getSalary)
        .reduce(Integer::min);
System.out.println("最低薪资: " + minSalary.orElse(0));

// 5. 计算年龄之和
int totalAge = personList.stream()
        .map(Person::getAge)
        .reduce(0, Integer::sum);
System.out.println("总年龄: " + totalAge);

5.4 collect(重要)

//收集到 List集合
List<String> names = personList.stream()
        .map(Person::getName)
        .collect(Collectors.toList());
//收集到 Set集合
Set<String> cities = personList.stream()
        .map(Person::getArea)
        .collect(Collectors.toSet());
//收集到 Map集合
Map<Integer, String> idToNameMap = personList.stream()
        .collect(Collectors.toMap(Person::getId, Person::getName));

Map<Integer, Person> idToPersonMap = personList.stream()
        .collect(Collectors.toMap(Person::getId, v -> v));
//收集到自定义集合
List<Person> sortedList = personList.stream()
        .sorted(Comparator.comparing(Person::getAge))
        .collect(Collectors.toList());
//使用 Collectors.joining 连接字符串
String namesString = personList.stream()
        .map(Person::getName)
        .collect(Collectors.joining(", "));
//Collectors.groupingBy
Map<String, List<Person>> cityToPeopleMap = personList.stream()
        .collect(Collectors.groupingBy(Person::getArea));
//使用 Collectors.partitioningBy 分区
Map<Boolean, List<Person>> isAdultMap = personList.stream()
        .collect(Collectors.partitioningBy(person -> person.getAge() >= 18));
//使用 Collectors.summarizingInt 计算统计信息
IntSummaryStatistics salarySummary = personList.stream()
        .collect(Collectors.summarizingInt(Person::getSalary));
double average = salarySummary.getAverage();//平均值
int max = salarySummary.getMax();//最大值
long count = salarySummary.getCount();//计数
int min = salarySummary.getMin();//最小值
long sum = salarySummary.getSum();//求和

5.5 min、max、count

Optional<Person> maxSalaryPerson = personList.stream()
                                             .max(Comparator.comparing(Person::getSalary));
Optional<Person> minAgePerson = personList.stream()
                                          .min(Comparator.comparing(Person::getAge));
long count = personList.stream().count();

5.6 组合使用

这段代码首先计算所有 Person 对象的工资总和,然后找到年龄最大的 Person 对象,最后将所有 Person 对象的名字收集到一个 List 中。

int totalSalary = personList.stream()
                            .mapToInt(Person::getSalary)
                            .reduce(0, Integer::sum);

Optional<Person> oldestPerson = personList.stream()
                                         .max(Comparator.comparing(Person::getAge));

List<String> names = personList.stream()
                               .map(Person::getName)
                               .collect(Collectors.toList());

6 短路的终端操作

6.1 anyMatch

boolean hasFemale = personList.stream()
                              .anyMatch(person -> "Female".equals(person.getGender()));

6.2 allMatch

boolean allAdults = personList.stream()
                              .allMatch(person -> person.getAge() >= 18);

6.3 noneMatch

boolean noRetired = personList.stream()
                              .noneMatch(person -> person.getAge() >= 65);

6.4 findFirst

Optional<Person> firstPerson = personList.stream()
                                         .findFirst();

6.5 findAny

Optional<Person> anyPerson = personList.stream()
                                       .findAny();

6.6 组合使用

这段代码首先检查是否存在女性,然后找到第一个成年人,最后将所有成年人的名字收集到一个 List 中。

boolean hasFemale = personList.stream()
                              .anyMatch(person -> "Female".equals(person.getGender()));

Optional<Person> firstAdult = personList.stream()
                                        .filter(person -> person.getAge() >= 18)
                                        .findFirst();

List<String> names = personList.stream()
                               .filter(person -> person.getAge() >= 18)
                               .map(Person::getName)
                               .collect(Collectors.toList());

7 并行流

并行流可以提高处理大数据集时的性能。Java Stream API 的并行处理是基于 Java 的 Fork/Join 框架实现的。Fork/Join 框架是 Java 7 引入的一种并行计算框架,它可以将一个大任务拆分成多个小任务,然后在多个处理器上并行执行这些小任务,最后将结果合并。

在 Stream API 中,并行流是通过 parallelStream() 方法创建的。当你调用 parallelStream() 方法时,Stream API 会创建一个 ForkJoinTask,并将其提交给 ForkJoinPool 执行。ForkJoinPool 是一个特殊的线程池,它使用工作窃取算法来平衡任务执行,从而提高并行处理效率。

String allNames = personList.parallelStream()
    .map(Person::getName)
    .collect(Collectors.joining(", "));
System.out.println("All Names (Parallel): " + allNames);

8 总结

Stream API 的主要特点包括:

  1. 简洁性:Stream API 提供了一种简洁的方式来处理集合数据,使得代码更加易读、易写。
  2. 可读性:Stream API 的操作可以链式调用,使得代码更加清晰、易读。并行处理:Stream API 支持
  3. 并行处理,可以充分利用多核处理器的能力。
  4. 惰性求值:Stream API 的操作是惰性求值的,即只有在需要结果时才会执行操作。
  5. 无状态操作:Stream API 的无状态操作不会改变流中的元素,也不会改变流的状态。
  6. 有状态操作:Stream API 的有状态操作会改变流的状态,或者依赖于流中的其他元素。
  7. 短路操作:Stream API 的短路操作会在满足某个条件时提前结束处理,并返回一个结果。
  8. 终端操作:Stream API 的终端操作会处理流中的所有元素,并返回一个结果。

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot整合lua脚本在Redis实现商品库存扣减

1、目的 使用lua脚本&#xff0c;可以保证多条命令的操作原子性&#xff1b;同时可以减少操作IO&#xff08;比如说判断redis对应数据是否小于0&#xff0c;小于0就重置为100&#xff0c;这个场景一般是取出来再判断&#xff0c;再存放进行&#xff0c;就至少存在2次IO,用lua脚…

深入了解 Spring IOC,AOP 两大核心思想

文章目录 一、Spring 基础 - 控制反转&#xff08;IOC&#xff09;1.1. 引入1.2. 如何理解 IOCSpring Bean 是什么&#xff1f;IoC 是什么&#xff1f;IoC 能做什么&#xff1f;IoC 和 DI 是什么关系&#xff1f; 1.3. IoC 配置的三种方式xml 配置Java 配置注解配置 1.4. 依赖注…

HNU_多传感器(专选)_作业4(构建单层感知器实现分类)

1. (论述题)&#xff08;共1题&#xff0c;100分&#xff09; 假设平面坐标系上有四个点&#xff0c;要求构建单层感知器实现分类。 (3,3),(4,3) 两个点的标签为1&#xff1b; (1,1),(0,2) 两个点的标签为-1。 思路&#xff1a;要分类的数据是2维数据&#xff0c;需要2个输入…

dolphinscheduler服务RPC框架源码解析(二)RPC核心注解@RpcService和@RpcMethod设计实现

1.工程目录 从3.2.1版本之后这个dolphinscheduler中的RPC框架工程就从原来的dolphinscheduler-remote工程重构到了dolphinscheduler-extract工程。 dolphinscheduler 父项目 dolphinscheduler-extract RPC服务项目 dolphinscheduler-extract-alert 监控告警服务RPC接口定义、…

CentOS 上如何查看 SSH 服务使用的端口号?

我们知道&#xff0c;linux操作系统中的SSH默认情况下&#xff0c;端口是使用22&#xff0c;但是有些线上服务器并不是使用的默认端口&#xff0c;那么这个时候&#xff0c;我们应该如何快速知道SSH使用的哪个端口呢&#xff1f; 1、通过配置文件查看 cat /etc/ssh/sshd_confi…

基于深度学习的猫狗识别系统【深度学习课设】

&#x1f3c6; 作者简介&#xff1a;席万里 ⚡ 个人网站&#xff1a;https://dahua.bloggo.chat/ ✍️ 一名后端开发小趴菜&#xff0c;同时略懂Vue与React前端技术&#xff0c;也了解一点微信小程序开发。 &#x1f37b; 对计算机充满兴趣&#xff0c;愿意并且希望学习更多的技…

Java常用 Date 时间格式化、Calender日历、正则表达式的用法

目录 1. SimpleDateFormat 日期格式化类 1.1 Date 类型转 String 1.2 String 类型转 Date 2. Calendar 日历类 3. 正则表达式 3.1 正则表达式的组成部分 3.2 手机号正则表达式 3.3 常用密码校验正则表达式 1. SimpleDateFormat 日期格式化类 SimpleDateFormat 是Java中…

MySQL其四,各种函数,以及模拟了炸裂函数创建用户等操作

目录 一、MySQL中的函数 1、IFNULL 2、IF 3、case &#xff08;难点&#xff09; 4、exists(难) --存在的意思 二、常见的函数 1、字符串函数 2、数学函数 3、日期函数 &#xff08;使用频率不是很高&#xff09; 4、其他函数 5、关于字符集的问题 6、mysql炸裂函数…

USB-TypeC接口设计

USB-TypeC介绍 一个全的TypeC接口一共有24个引脚,分别是A1~A12和B1~B12,并且是左右镜像对称支持正反插,TypeC向下兼容USB2.0不需要USB3.0的信号时,TypeC可以进一步简化成12pin如下图所示,因此TypeC的种类是比较多的。 USB3.2和USB4包括之后的USB的接口都是…

Dual-Write Problem 双写问题(微服务)

原文链接https://www.confluent.io/blog/dual-write-problem/ 双写问题发生于当两个外部系统必须以原子的方式更新时。 问题 说有人到银行存了一笔钱&#xff0c;触发 DepositFunds 命令&#xff0c;DepositFunds 命令被发送到Account microservice。 Account microservice需…

短信验证码burp姿势

首先声明&#xff0c;本文仅仅作为学习使用&#xff0c;因个人原因导致的后果&#xff0c;皆有个人承担&#xff0c;本人没有任何责任。 在之前的burp学习中&#xff0c;我们学习了图片验证码的突破&#xff0c;但是现实中还有很多短信验证码&#xff0c;在此我介绍几种短信验…

2024 X-GAME 上海智能新能源汽车大数据竞赛决赛顺利举行,和鲸Heywhale连续五年助推新能源汽车产业发展

11月22日&#xff0c;第七届 X-GAME 上海智能新能源汽车大数据竞赛圆满落幕&#xff01;这是和鲸作为协办方第五年为 X-GAME 新能源汽车分析赛道提供全程支持&#xff0c;赋能新能源汽车的产业发展。自 2018 年首次举办以来&#xff0c;以“数联万物&#xff0c;车载未来”为主…

Referer头部在网站反爬虫技术中的运用

网站数据的安全性和完整性至关重要。爬虫技术&#xff0c;虽然在数据收集和分析中发挥着重要作用&#xff0c;但也给网站管理员带来了挑战。为了保护网站数据不被恶意爬取&#xff0c;反爬虫技术应运而生。本文将探讨HTTP头部中的Referer字段在反爬虫技术中的应用&#xff0c;并…

【ubuntu】将Chroma配置为LINUX服务

Chroma是一个轻量级向量数据库。既然是数据库&#xff0c;那么我希望它是能够长时间运行。最直接的方式是配置为service服务。 可惜官方没有去提供配置为服务的办法&#xff0c;而鄙人对docker又不是特别感冒。所以自己研究了下chroma配置为服务的方式。 系统&#xff1a;ubu…

jenkins harbor安装

Harbor是一个企业级Docker镜像仓库‌。 文章目录 1. 什么是Docker私有仓库2. Docker有哪些私有仓库3. Harbor简介4. Harbor安装 1. 什么是Docker私有仓库 Docker私有仓库是用于存储和管理Docker镜像的私有存储库。Docker默认会有一个公共的仓库Docker Hub&#xff0c;而与Dock…

vscode 打开 setting.json

按下Ctrl Shift P&#xff08;Windows/Linux&#xff09;或Cmd Shift P&#xff08;Mac&#xff09;来打开命令面板。输入open settings&#xff0c;然后选择 Open User Settings(JSON)。打开settings.json文件 ------修改设置-----&#xff1a; 1、 html代码的行长度&am…

在conda终端运行Jupyter Notebook

文章目录 创建并激活环境安装并匹配ipykernel打开Jupyter Notebook 创建并激活环境 在Anaconda Prompt中输入conda create --name OpenAI来创建新的环境&#xff0c;其中OpenAI为新环境的名字 如果不需要创建新的环境&#xff0c;则直接激活已有环境。输入conda activate Open…

【机器学习算法】——决策树:CART

文章目录 理论sklearn 库实现完整代码 理论 CART全称叫Classification and Regression Tree&#xff0c;即分类与回归树。CART假设决策树是二叉树&#xff0c;内部结点特征的取值只有“是”和“否”&#xff0c;左分支是取值为“是”的分支&#xff0c;有分支则相反。这样的决…

Pytest-Bdd-Playwright 系列教程(15):背景(Background)

Pytest-Bdd-Playwright 系列教程&#xff08;15&#xff09;&#xff1a;背景&#xff08;Background&#xff09; 前言一、什么是背景&#xff08;Background&#xff09;二、特性文件三、测试脚本四、运行测试总结 前言 在测试的过程中&#xff0c;我们往往会遇到这样的问题&…

【精】Linux虚拟机 Docker 配置阿里云镜像加速

一、前言 1.1 拉取镜像报错 当 Docker 客户端拉取镜像时报错&#xff0c;类似如下&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while 报错解释&#xff1a; 这个错误表明 Docker 客户端尝试与 …