Java基础关键_018_集合(二)

目  录

一、泛型 ※

1.说明

2.实例 

3.擦除与补偿

4.泛型的定义

(1)类定义

(2)静态方法定义

(3)接口定义

5.通配符

(1)无限定

(2)上限

(3)下限

二、集合迭代的并发修改异常

1.示例

2.说明

3. fail-fast 机制实现原理

三、List 接口

1.特点

2.常见实现类

3.特有方法

(1)add(int index, E element) 

(2) set(int index, E element) 

(3) get(int index)

(4)remove(int index)

(5)indexOf(Object o)

(6)lastIndexOf(Object o)

(7)subList(int fromIndex, int toIndex)

(8)of(E... elements)

4.特有迭代

(1)listIterator()

(2) listIterator(int index)

四、ListIterator 的方法

1.hasNext()

2.next()

3.remove()

4.add(E e) 

5.hasPrevious()

6.previous()

7.nextIndex()

8.previousIndex()

9.set(E e)

五、比较 

1.回顾数组 Comparable 比较

2.集合 Comparator 比较


一、泛型 ※

1.说明

  1. jdk 5 新增,属于编译阶段功能;
  2. 不使用泛型,会导致代码冗长,从集合中抽取的元素若要访问子类中特有的方法,需要向下转型;
  3. 泛型可以在开发时指定集合中存储的数据类型;
  4. 使用泛型除了可以简化代码,避免类型转换操作之外,还可以在编译时进行类型检查,避免了在运行时出现类型错误的问题;
  5. jdk 7 之后,可以省略表达式后面的泛型类型。

2.实例 

public class GenericTest {public static void main(String[] args) {
//        Collection<Person> c = new ArrayList<Person>();   //  jdk 1.7之前,必须写后面的泛型类型Collection<Person> c = new ArrayList<>();   //  jdk 1.7之后,可以省略后面的泛型类型// Collection<Person> c = new ArrayList<Person>();Person p1 = new Person("张三");Person p2 = new Person("李四");Person p3 = new Person("王五");c.add(p1);c.add(p2);c.add(p3);
//        c.add("赵六");    // 报错,类型不匹配Iterator<Person> iterator = c.iterator();while (iterator.hasNext()) {Person p = iterator.next();p.eat();}/** 张三正在吃饭!* 李四正在吃饭!* 王五正在吃饭!* */}
}

3.擦除与补偿

  1. 泛型的出现提高了编译时的安全性,在编译时对数据类型进行检查,属于编译时期的技术。加载类时,会将泛型擦除,擦除后类型为 Object 类型;

  2. 泛型擦除是为了让 jdk 5 与之前版本的 jdk 能够兼容同一个类加载器;

  3. 因为泛型擦除后,变为 Object 类型。为了保证获得集合元素类型为实际类型,虚拟机会根据元素实际类型自动进行向下转型,这一过程称为泛型补偿。


4.泛型的定义

(1)类定义

public class GenericTest<T> {private T name;public T getName() {return name;}public void setName(T name) {this.name = name;}public GenericTest(T name) {this.name = name;}public static void main(String[] args) {GenericTest<String> gt = new GenericTest<>("张三");System.out.println(gt.getName());
//        GenericTest<String> gt1 = new GenericTest<>(123);   // 报错,类型不匹配,应该是String类型}
}

(2)静态方法定义

public class GenericTest {public static <E> void test(E[] elts) {for (E elt : elts) {System.out.print(elt + "\t");}// 1	2	3	4	5}public static void main(String[] args) {Integer[] ints = {1, 2, 3, 4, 5};GenericTest.test(ints);}
}

(3)接口定义

public interface GenericTest01<T> {String get(T t);
}
public class GenericTest01Impl implements GenericTest01<GenericTest01Impl> {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public GenericTest01Impl(String name) {this.name = name;}@Overridepublic String get(GenericTest01Impl gti) {return getName();}public static void main(String[] args) {GenericTest01Impl gt = new GenericTest01Impl("GenericTest01Impl");System.out.println(gt.get(gt));    // GenericTest01Impl}
}

5.通配符

(1)无限定

        【 <?> 】,其中 【 ? 】 可以是任意引用数据类型。

public class GenericTest {public static void get(ArrayList<?> list) {}public static void main(String[] args) {get(new ArrayList<String>());get(new ArrayList<Integer>());get(new ArrayList<Double>());get(new ArrayList<Object>());}
}

(2)上限

        【 <? extends T> 】,其中 【 ? 】 必须是 T 及其子类。

public class GenericTest {public static void get(ArrayList<? extends Number> list) {}public static void main(String[] args) {
//        get(new ArrayList<String>());   // 报错, 不能将类型为java.util.ArrayList<java.lang.String>的表达式赋给类型为java.util.ArrayList<? extends java.lang.Number>的变量get(new ArrayList<Integer>());get(new ArrayList<Double>());
//        get(new ArrayList<Object>());   // 报错, 不能将类型为java.util.ArrayList<java.lang.Object>的表达式赋给类型为java.util.ArrayList<? extends java.lang.Number>的变量}
}

(3)下限

        【 <? super T> 】,其中 【 ? 】 必须是 T 及其父类。

public class GenericTest {public static void get(ArrayList<? super Number> list) {}public static void main(String[] args) {
//        get(new ArrayList<String>());  // 报错,不允许
//        get(new ArrayList<Double>());   // 报错,不允许get(new ArrayList<Object>());get(new ArrayList<Number>());}
}

二、集合迭代的并发修改异常

1.示例

        在进行集合迭代需要三个步骤,可以参考 Java基础关键_017_集合(一) ,但是在删除集合中的元素时,会抛出并发修改异常,示例如下:

public class GenericTest {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String name = iterator.next();if (name.equals("李四")) {list.remove(name);  // 调用集合remove方法删除元素会报错 java.util.ConcurrentModificationException(并发修改异常)}System.out.println(name);}}
}

        面对以上异常,应该怎么做呢?

        应该将集合的 remove 方法替换为迭代器的 remove 方法,在第二次迭代时就会发现“李四”被删除了,示例如下:

public class GenericTest {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String name = iterator.next();if (name.equals("李四")) {iterator.remove();  // 调用迭代器的remove方法删除当前元素}}Iterator<String> iterator1 = list.iterator();while (iterator1.hasNext()) {String name = iterator1.next();System.out.println(name);}}
}

2.说明

        因为使用迭代器遍历,而使用集合删除操作去删除,底层为防止多线程导致的错误发生,所以抛出并发修改异常,这一机制称为快速失败,即 fail-fast 。


3. fail-fast 机制实现原理

  1. 集合中设置有 modCount 属性,记录修改次数使用集合对象进行 增、删、改 操作时,modCount 会加 1 ;

  2. 获取迭代器对象时,会初始化一个 expectedModCount 属性,并将其值初始化为 modCount ;

  3. 当使用集合的 remove 方法删除元素时,会导致 modCount 加 1 ,而 expectedModCount 不变;

  4. 当 modCount 和 expectedModCount 值不相等时,底层代码会抛出并发修改异常。


三、List 接口

1.特点

        有序、可重复。


2.常见实现类

  1. ArrayList:数组;
  2. Vector、Stack:线程安全的数组;
  3. LinkedList:双向链表。


3.特有方法

        只适合在 List 中使用,都与下标有关。

(1)add(int index, E element) 

        在指定索引处插入元素。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add(1, "赵六");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {System.out.print(iterator.next() + "\t");}// 张三	赵六	李四	王五	}
}

(2) set(int index, E element) 

        修改索引处的元素。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.set(0, "赵六");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {System.out.print(iterator.next() + "\t");}// 赵六	李四	王五}
}

(3) get(int index)

        根据索引获取元素。List 集合独特的遍历方式:通过下标遍历。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");System.out.println(list.get(1));    // 李四}
}

(4)remove(int index)

        删除索引处的元素。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.remove(1);for (String s : list) {System.out.println(s);}// 张三// 王五}
}

(5)indexOf(Object o)

        获取对象 o 在集合中第一次出现的索引。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("张三");list.add("王五");System.out.println(list.indexOf("张三")); // 0}
}

(6)lastIndexOf(Object o)

         获取对象 o 在集合中最后一次出现的索引。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("张三");list.add("王五");System.out.println(list.lastIndexOf("张三")); // 2}
}

(7)subList(int fromIndex, int toIndex)

        截取子 List 集合,生成一个新的集合,范围是 [ fromIndex, toIndex )。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("张三");list.add("王五");System.out.println(list.subList(1, 3)); // [李四, 张三]}
}

(8)of(E... elements)

        静态方法,返回包含任意数量元素的不可修改列表,所获取的集合是只读的。

public class ListTest {public static void main(String[] args) {List<String> strings = List.of("H", "e", "l", "l", "o");strings.set(1, "Q");    // 报错,java.lang.UnsupportedOperationException}
}

4.特有迭代

(1)listIterator()

        获取 List 集合特有的迭代器。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");/** 通用迭代器* */Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String next = iterator.next();System.out.print("Iterator:" + next + "\t");}// Iterator:张三	Iterator:李四	Iterator:王五	Iterator:赵六System.out.println();/** 特有迭代器* */ListIterator<String> listIterator = list.listIterator();while (listIterator.hasNext()) {String next = listIterator.next();System.out.print("ListIterator:" + next + "\t");}// ListIterator:张三	ListIterator:李四	ListIterator:王五	ListIterator:赵六}
}

(2) listIterator(int index)

        从列表指定位置开始,返回列表中元素的列表迭代器。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");/** 特有迭代器* */ListIterator<String> listIterator = list.listIterator(2);while (listIterator.hasNext()) {String next = listIterator.next();System.out.print(next + "\t");}// 王五	赵六}
}

四、ListIterator 的方法

1.hasNext()

        通用方法,判断当前指向位置是否有元素。


2.next()

        通用方法,将当前指向元素返回,并指向下一位。


3.remove()

        通用方法,删除上一次 next() 方法返回的数据。必须先调用 next() 方法或 previous() 方法,否则会报错。


4.add(E e) 

        特有方法,将元素添加到指向位置,然后指向下一位。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");ListIterator<String> listIterator = list.listIterator();while (listIterator.hasNext()) {if ("王五".equals(listIterator.next())){listIterator.add("冯七");}}System.out.println(list);   // [张三, 李四, 王五, 冯七, 赵六]}
}

5.hasPrevious()

        特有方法,判断当前指向位置的上一个位置是否存在元素。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");ListIterator<String> listIterator = list.listIterator();System.out.println(listIterator.hasPrevious()); // falsewhile (listIterator.hasNext()) {listIterator.next();}System.out.println(listIterator.hasPrevious()); // true}
}

6.previous()

        特有方法,获取上一个元素,即指向上一个元素并返回。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");ListIterator<String> listIterator = list.listIterator();while (listIterator.hasNext()) {listIterator.next();}System.out.println(listIterator.previous()); // 赵六System.out.println(listIterator.previous()); // 王五}
}

7.nextIndex()

        特有方法,获取指向位置的下标。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");ListIterator<String> listIterator = list.listIterator();while (listIterator.hasNext()) {listIterator.next();}System.out.println(listIterator.nextIndex()); // 4System.out.println(listIterator.previous()); // 赵六System.out.println(listIterator.nextIndex()); // 3}
}

8.previousIndex()

        特有方法,获取指向位置的上一个位置的下标。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");ListIterator<String> listIterator = list.listIterator();while (listIterator.hasNext()) {listIterator.next();}System.out.println(listIterator.previousIndex()); // 3System.out.println(listIterator.previous()); // 赵六System.out.println(listIterator.previousIndex()); // 2}
}

9.set(E e)

        特有方法,修改上一次 next() 方法返回的数据。必须先调用 next() 方法或 previous() 方法,否则会报错。

public class ListTest {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");list.add("赵六");ListIterator<String> listIterator = list.listIterator();while (listIterator.hasNext()) {if ("王五".equals(listIterator.next())) {listIterator.set("冯七");}}System.out.println(list);   // [张三, 李四, 冯七, 赵六]}
}

五、比较 

1.回顾数组 Comparable 比较

public class Student implements Comparable<Student>{private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {
//        return this.age - o.age;    // 比较规则, 年龄升序//        return o.age - this.age;    // 比较规则, 年龄降序//        return this.name.compareTo(o.name);    // 比较规则,姓名升序return o.name.compareTo(this.name);    // 比较规则,姓名降序}
}
public class ComparableTest {public static void main(String[] args) {Student s1 = new Student("张三", 18);Student s2 = new Student("李四", 22);Student s3 = new Student("王五", 7);Student[] students = {s1, s2, s3};Arrays.sort(students);System.out.println(Arrays.toString(students));}
}

2.集合 Comparator 比较

public class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class StudentComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();   // 排序规则,年龄升序//        return o2.getAge() - o1.getAge();   // 排序规则,年龄降序//        return o1.getName().compareTo(o2.getName());    // 排序规则,姓名升序//        return o2.getName().compareTo(o1.getName());    // 排序规则,姓名降序}
}
public class ComparatorTest {public static void main(String[] args) {List<Student> students = new ArrayList<>();students.add(new Student("张三", 18));students.add(new Student("李四", 22));students.add(new Student("王五", 7));students.sort(new StudentComparator());ListIterator<Student> iterator = students.listIterator();while (iterator.hasNext()){System.out.println(iterator.next());}}
}

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

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

相关文章

FPGA学习篇——Verilog学习3(关键字+注释方法+程序基本框架)

1 Verilog常用关键字 大概知道以下哪些是关键字就好&#xff0c;如何使用还是得在编写代码中来学习。 2 Verilog注释方法 Verilog有两种注释方式&#xff1a; 2.1 “ // ” 单行。 2.2 “ /* ... */ ” 可扩展多行。 3 Verilog程序基本框架 Verilog 的基本设计单元是“…

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输 Usb 通信 你也许会有疑问&#xff0c;明明有这么多通信方式和数据传输&#xff08;SPI、I2C、UART、以太网&#xff09;为什么偏偏使用USB呢? 原因有很多&#xff0c;如下&#xff1a; 1. 高速数据传输能力 高带宽&#xff1a;USB接口提供了较高的数据传…

深入理解与配置 Nginx TCP 日志输出

一、背景介绍 在现代网络架构中&#xff0c;Nginx 作为一款高性能的 Web 服务器和反向代理服务器&#xff0c;广泛应用于各种场景。除了对 HTTP/HTTPS 协议的出色支持&#xff0c;Nginx 从 1.9.0 版本开始引入了对 TCP 和 UDP 协议的代理功能&#xff0c;这使得它在处理数据库…

【大模型安全】安全解决方案

【大模型安全】安全解决方案 1.技术层面2.数据层面数据收集阶段训练阶段模型推理阶段 1.技术层面 在使用大语言模型时&#xff0c;通常有几种选择&#xff1a;一种是采用封装好的大语言模型SaaS云服务&#xff1b;另一种是在公有云上部署自有的大语言模型&#xff0c;并通过权…

python中httpx库的详细使用及案例

文章目录 1. 安装 httpx2. 同步请求3. 异步请求4. 高级功能5. 错误处理6. 配置客户端7. 结合 Beautiful Soup 使用8. 示例:抓取并解析网页9. 注意事项httpx 是一个现代化的 Python HTTP 客户端库,支持同步和异步请求,功能强大且易于使用。它比 requests 更高效,支持 HTTP/2…

OpenCV计算摄影学(19)非真实感渲染(Non-Photorealistic Rendering, NPR)

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 非真实感渲染&#xff08;Non-Photorealistic Rendering, NPR&#xff09;是一种计算机图形学技术&#xff0c;旨在生成具有艺术风格或其他非现实…

微信小程序点击按钮,将图片下载到本地

前言&#xff1a; 最近在公司完成一个小程序的时候需要实现一个功能&#xff1a;点击按钮获取用户相册权限&#xff0c;将图片下载到用户本地相册&#xff0c;经过了好几次的尝试最终算是实现了。将总结的经验在这里分享给小伙伴们。 实现方式&#xff1a; //.wxml文件 <…

数据仓库为什么要分层

数据仓库分层架构是数据仓库设计中的一个重要概念&#xff0c;其主要目的是为了更好地组织和管理数据&#xff0c;提高数据仓库的可维护性、可扩展性和性能。分层架构将数据仓库划分为多个层次&#xff0c;每个层次都有其特定的职责和功能。以下是数据仓库分层的主要原因和好处…

selenium库

一、什么是selenium库&#xff1f; selenim是一个用于Web应用程序自动化测试工具&#xff0c;selenium测试直接运行在浏览器中 像真正的用户在操作一样&#xff0c;驱动浏览器执行特定的动作&#xff0c;如点击&#xff0c;下拉等操作 二、selenium在爬虫中的应用 获取动态…

python从入门到精通(二十四):python爬虫实现登录功能

这里写目录标题 requests实现登录功能selenium实现登录功能 requests实现登录功能 使用 requests 库结合会话&#xff08;Session&#xff09;来尝试登录。不过豆瓣有反爬虫机制&#xff0c;这种方式可能会受到验证码等因素的限制 import requests import re# 豆瓣登录页面 l…

十七、从0开始卷出一个新项目之瑞萨RZN2L定时器(GPT)+DMA生成PWM的运动控制

一、概述 嵌入式科普(34)通过对比看透DMA的本质 分享瑞萨RZN2L使用DMA生成PWM的运动控制的例程源码 rzn2l必要的外设资源&#xff1a; rzn2l拥有32-bit timer General PWM Timer (GPT) with 18 channels CPU、GPT最高频率400Mhz DMAC0 and DMAC1 8 channels 8 channels 还…

MR的环形缓冲区(底层)

MapReduce的大致流程&#xff1a; 1、HDFS读取数据&#xff1b; 2、按照规则进行分片&#xff0c;形成若干个spilt&#xff1b; 3、进行Map 4、打上分区标签&#xff08;patition&#xff09; 5、数据入环形缓冲区&#xff08;KVbuffer&#xff09; 6、原地排序&#xff…

解锁STM32外设:开启嵌入式开发新世界

✨✨✨这里是小韩学长yyds的BLOG(喜欢作者的点个关注吧) ✨✨✨想要了解更多内容可以访问我的主页 小韩学长yyds-CSDN博客 目录 探索 STM32 强大的外设家族 初窥门径&#xff1a;STM32 外设开发基础 开发方式与工具 外设配置基础步骤 深入剖析&#xff1a;常见外设应用实例…

大模型AI平台DeepSeek 眼中的SQL2API平台:QuickAPI、dbapi 和 Magic API 介绍与对比

目录 1 QuickAPI 介绍 2 dbapi 介绍 3 Magic API 介绍 4 简单对比 5 总结 统一数据服务平台是一种低代码的方式&#xff0c;实现一般是通过SQL能直接生成数据API&#xff0c;同时能对产生的数据API进行全生命周期的管理&#xff0c;典型的SQL2API的实现模式。 以下是针对…

人工智能之数学基础:对线性代数中逆矩阵的思考?

本文重点 逆矩阵是线性代数中的一个重要概念,它在线性方程组、矩阵方程、动态系统、密码学、经济学和金融学以及计算机图形学等领域都有广泛的应用。通过了解逆矩阵的定义、性质、计算方法和应用,我们可以更好地理解和应用线性代数知识,解决各种实际问题。 关于逆矩阵的思…

[傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中

[傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中 将MathType公式编辑器内嵌到WPS工具栏中 下载好所需文件 我用夸克网盘分享了「mathtype安装教程超简单易上手.zip」&#xff0c;点击链接即可保存。打开「夸克APP」 链接&#xff1a;https://pan.quark.cn/s/4726c684…

WPF框架---MvvmLight介绍

目录 1. MvvmLight 框架准备 2. MvvmLight 中的相关基类 3. MvvmLight 中的数据绑定与通知 a. 核心功能 b. 关键方法与属性 c. 完整示例 d. 高级用法 4. MvvmLight 中的命令对象 a. 命令对象的作用 b. 核心接口&#xff1a;ICommand c. MvvmLight 中的 RelayCommand…

【Linux】线程同步与互斥

线程同步与互斥 一.线程互斥1.互斥相关概念2.互斥锁 Mutex3.互斥锁接口4.互斥锁实现原理5.互斥锁封装 二.线程同步1.同步相关概念2.条件变量 Condition Variable3.条件变量接口4.条件变量封装5.信号量 Semaphore6.信号量接口7.信号量封装8.生产者 - 消费者模型1.基于 Blocking …

URIError: URI malformed

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

linux c++11 gcc4 环境编译安装googletest/gtest v1.10

c11对应googletest/gtest 经过测试&#xff0c;c11对应版本是googletest v1.10.x 编译安装 编译环境 sudo apt-get update sudo apt-get install -y build-essential cmake下载或git clone代码 git clone https://github.com/google/googletest.git cd googletest git che…