初识Java 10-1 集合

目录

泛型和类型安全的集合

基本概念

添加一组元素

打印集合

List

Iterator(迭代器)


本笔记参考自: 《On Java 中文版》


        在进行程序设计时我们会发现,程序总是会根据某些在运行时才能知道的条件来创建新的对象。这意味着,我们必须能够随时随地创建任意数量的对象。

        Java提供了几种方法来持有对象(的引用),其中之一就是数组。数组的优点在于其的高效,但其本身却会受到自身大小固定的制约。实际上,Java.util库提供了一组集合类来解决这一问题,其中包括的基本类ListSetQueueMap也被称为容器类

    Java并没有直接为集合提供关键字支持。

泛型和类型安全的集合

        在Java 5之前,编译器允许向集合中插入不正确的类型。在举例之前需要先对ArrayList类进行一些必要的说明:

        ArrayList是是一种泛型类型,它实现了迭代器(Iterable)、CollectionList等接口。泛型是一种参数化类型的机制,在这种机制下,形参的数据类型也会成为可传输的参数。因为泛型的存在,ArrayList可以存储任何类型的对象,而不需要在使用前进行类型转换(本段参考​林二月er​的博客、讯飞星火提供的信息)

    ArrayList使用一个数值来查找对应对象。从某种意义上,ArrayList将数值和对象关联起来了。

        下例中出现的ArrayList是一个反例,它没有使用泛型:

import java.util.ArrayList;class Apple {private static long counter;private final long id = counter++;public long id() {return id;}
}class Orange {
}public class AppleAndOrangesWithoutGenerics {@SuppressWarnings("unchecked") // 参数unchecked表示只有“unchecked”警告应该被忽略public static void main(String[] args) {ArrayList apples = new ArrayList<>();for (int i = 0; i < 3; i++)apples.add(new Apple());apples.add(new Orange()); // 注意:插入的是一个Orange类型,这本来应该是错误的操作for (Object apple : apples) {((Apple) apple).id(); // 需要强制类型转换,此时Orange只有在运行时才会被检测出来}}}

        上述程序的错误不会在编译时被发现,这个报错会出现在运行时:

        AppleOrange唯一的联系在于它们都继承了Object类。ArrayList持有的也是Object,所以无论是Apple类还是Orange类都能被加入其中(并且不会引发报错)。此时会从ArrayList中取出Object类型的引用,若想使用引用还必须强制类型转换。也正是在运行时,程序尝试将Orange对象转型为Apple时才会发现错误。

        若要定义一个持有Apple对象的ArrayList,应该使用:

ArrayList<Apple>

尖括号包围的是类型参数(可以有多个),它指定了集合实例中可以保存的类型。

        下面是修改后的例子:

import java.util.ArrayList;public class AppleAndOrangesWithGenerics {public static void main(String[] args) {ArrayList<Apple> apples = new ArrayList<>();for (int i = 0; i < 3; i++)apples.add(new Apple());// 此时,下方的做法就会引发编译时错误// apples.add(new Orange());for (Apple apple : apples)System.out.println(apple.id());}
}

        程序执行的结果如下:

        上述程序中,出现了语句 ArrayList<Apple> apples = new ArrayList<>(); 。这种语句因为<>符号,也被称为“钻石语法”。在Java 7之前,这种语法的使用会更加复杂:

ArrayList<Apple> apples = new ArrayList<Apple>(); // 需要在表达式的两侧重复写出类型声明

随着类型的深入,上述这种语法会变得越发复杂。因此最后被现在这种更为简便的语法代替了。

        泛型的存在使得我们从List(接口)中获取对象时,无须进行转型了。因为List知道它所持有的类型。另外,在泛型的情况下,向上转型也可以生效:

import java.util.ArrayList;class GrannySmith extends Apple {
}class Gala extends Apple {
}class Fuji extends Apple {
}class Braeburn extends Apple {
}public class GenericeAndUpcasting {public static void main(String[] args) {ArrayList<Apple> apples = new ArrayList<>();apples.add(new GrannySmith());apples.add(new Gala());apples.add(new Fuji());apples.add(new Braeburn());for (Apple apple : apples)System.out.println(apple);}
}

        程序执行的结果是:

        因为向上转型,所有可以向持有Apple对象的集合中,放入Apple的子类型。

    上述输出结果中,子对象名字后面的是由无符号十六进制表示的哈希码。

新特性:类型推断和泛型

        “局部变量类型推断”也可用于简化涉及泛型的定义:

import java.util.ArrayList;public class GenericTypeInference {void old() {ArrayList<Apple> apples = new ArrayList<>();}void modern() {var apples = new ArrayList<Apple>();}void pitFall() {var apples = new ArrayList<>();apples.add(new Apple());apples.get(0); // 会作为普通的Object类型返回}
}

        在modern()方法中,定义右侧使用的是<Apple>,通过这种方式提供信息,使编译器知道如何进行类型推断。

        但替代现有的语法时也可能会产生问题,在pitFall()方法中存在着语句

var apples = new ArrayList<>();

尽管这样也可以正常编译,但<>实际上会变为<Object>,这不是我们需要的。当我们想要从apples中提取元素时,它们会作为普通的Object类型返回,而不是具体的Apple类型。

基本概念

        Java的集合类库是用来“持有对象”的。从设计上,可以将这个库分为两种概念,这两种概念分别表示库的两个基本接口:

  1. Collection:一个由单独元素组成的序列,这些元素要符合一条或多条规则。

  2. Map:一组键值-对象对,使用键来查找值。Map也被称为关联数组(或是字典),它关联了对象与其他对象。

        在理想情况下,我们编写的大部分代码都是在和这些接口打交道,只有在创建的时候才需要指名所使用的确切类型。例如,按照这种思想创建一个List

List<Apple> apples = new ArrayList<>();

        和之前不同,ArrayList在这里被向上转型为了List。这样,在我们决定修改实现时,只需要修改创建的地方即可:

List<Apple> apples = new LinkedList<>(); // 将实现修改为LinkedList

        因此,通常会创建一个具体类的对象,并将其向上转型为相应的接口,在其余的代码中使用该接口

    但这种方法不会总是行得通,因为有些类会有额外的功能。当我们需要使用到这些额外的功能时,就无法将对象向上转型为更通用的接口了。

---

        序列是一种持有一组对象的方法,而Collection就是序列这一概念的一般化。例如:

import java.util.ArrayList;
import java.util.Collection;public class SimpleCollection {public static void main(String[] args) {Collection<Integer> c = new ArrayList<>();for (int i = 0; i < 10; i++)c.add(i); // 发生了自动装箱,向c中添加一个元素for (Integer i : c)System.out.print(i + " ");System.out.println();}
}

        程序执行的结果如下:

        这个示例只使用Collection中定义的方法,所以继承自该接口的类的任何对象都可以正常工作。不过,ArrayList是最基本的序列类型。

添加一组元素

        java.util中的ArraysCollection类都包含了一些工具方法,用于向一个Collection中添加一组元素:

  1. Arrays.asList():可以接受一个数组,或一个使用逗号分隔的元素列表,将其转换为一个List对象。
  2. Collection.addAll():接受一个Collection对象、一个数组或一个用都逗号分隔的列表,将其中的所有元素都添加到这个Collection中。
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;public class AddingGroups {public static void main(String[] args) {Collection<Integer> collection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));System.out.println("line 10: " + collection);Integer[] moreInts = { 6, 7, 8, 9, 10 };collection.addAll(Arrays.asList(moreInts)); // 传统的addAll()方法System.out.println("line 14: " + collection);// 下方的这种方式运行速度更快,但无法通过这种方式构建Collection。Collections.addAll(collection, 11, 12, 13, 14, 15);System.out.println("line 18: " + collection);Collections.addAll(collection, moreInts);System.out.println("line 20: " + collection);// 生成一个底层是数组的列表:List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);System.out.println("line 24: " + list);list.set(1, 99); // 可以进行元素的修改:将下标为1的元素值改为99// list.add(21); //运行时会发生报错,因为底层数组是不能调整大小的System.out.println("line 27: " + list);}
}

        运行结果如下(line后跟的是行号):

        Collection.addAll()的运行速度会快很多。因此,可以先构建一个没有元素的Collection,之后调用Collection.addAll()进行元素输入。

        collection.addAll(Arrays.asList(moreInts)); 表示该方法只能接受另一个Collection对象作为参数,使用限制较大。相比之下,Arrays.asList()Collection.addAll()方法就更加好用了。

        可以直接将Arrays.asList()的输出作为一个List进行使用,但这种方式进行的实现,其底层是数组,大小无法改变。

        也可以向Collection中添加子类型:

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;class Snow {}class Powder extends Snow {}class Light extends Powder {}class Heavy extends Powder {}class Crusty extends Snow {}class Slush extends Snow {}public class AsListInferecnce {public static void main(String[] args) {List<Snow> snow1 = Arrays.asList(new Crusty(), new Slush(), new Powder());// snow1.add(new Heavy()); // 发生异常List<Snow> snow2 = Arrays.asList(new Light(), new Heavy());// snow2.add(new Slush()); // 发生异常List<Snow> snow3 = new ArrayList<>();Collections.addAll(snow3, new Light(), new Heavy(), new Powder()); // 有一个可变参数列表snow3.add(new Crusty()); // 可以正常操作// 使用显式类型参数说明作为提示List<Snow> snow4 = Arrays.<Snow>asList(new Light(), new Heavy(), new Slush());// snow4.add(new Powder()); // 发生异常}
}

打印集合

        数组的打印往往需要借助于Arrays.toString()等方法,但就像之前的例子演示过的那样,集合类不需要这些:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;public class PrintingCollections {static Collection fill(Collection<String> collection) {collection.add("鼠");collection.add("猫");collection.add("狗");collection.add("狗");return collection;}static Map fill(Map<String, String> map) {map.put("鼠", "杰瑞");map.put("猫", "汤姆");map.put("狗", "斯派克");map.put("狗", "斯派克");return map;}public static void main(String[] args) {System.out.println(fill(new ArrayList<>()));System.out.println(fill(new LinkedList<>()));System.out.println();System.out.println(fill(new HashSet<>()));System.out.println(fill(new TreeSet<>())); // 按键的升序保存对象System.out.println(fill(new LinkedHashSet<>())); // 按添加顺序保存对象System.out.println();System.out.println(fill(new HashMap<>()));System.out.println(fill(new TreeMap<>())); // 按键的升序进行排序System.out.println(fill(new LinkedHashMap<>())); // 按插入顺序保存键,同时具有HashMap的查找速度}
}

        程序执行的结果是:

        上述例子演示了Java集合类库的两种主要类型。区别在于集合中的每个“槽”(slot)内持有的条目数:

  • Collection:每个槽这只保存一个条目。其中,List以指定顺序保存一组条目;Set中,同样的条目只能加入一个;Queue只能一端进,另一端出。
  • Map:每个槽内持有两个对象,即和与之关联的

        除此之外,上述例子中ArrayListLinkedList的区别不仅在于进行一些操作时性能上的差异,而且LinkedList包含的操作比ArrayList多。另一个值得注意的是与Hash相关的类,这种类使用的保存方式会不同于同属的其他类。

List

        List接口继承了Collection接口,并在此基础之上添加了一些方法,这些方法支持在List的中间进行元素的插入和移除。

        List会以特定的顺序维护元素,由其衍生出了许多有用的类:

        接下来会介绍其中两种较为常用的List

  • ArrayList:一种基本的List,擅长随机访问元素,但在List中间进行插入和删除速度较慢。
  • LinkedList:具有理想的顺序访问性能,插入和删除的成本较低。除此之外,随机访问性能也更差,但与ArrayList相比有更多的功能。

        下述程序将会用到的Pet类笔者只进行了简单实现,大致如下:

因此代码未写入本笔记。 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;public class ListFeatures {public static void main(String[] args) {List<Pet> pets = new ArrayList<>();Collections.addAll(pets, new Rat(), new Manx(),new Cymric(), new Pug(), new Cymric(), new Pug()); // 插入一些数据System.out.println("1. 创建List:" + pets);System.out.println();Hamster h = new Hamster();pets.add(h);System.out.println("2. 删除元素:" + pets);System.out.println("3. 确定对象是否存在:" + pets.contains(h)); // 按对象搜索pets.remove(h); // 按对象删除System.out.println();Pet tmpp = pets.get(2); // 按下标获取System.out.println("4. 获取元素下标:" + pets.indexOf(tmpp));System.out.println();Pet cymric = new Cymric();System.out.println("5. 试图通过同类对象进行索引:" + pets.indexOf(cymric));System.out.println("6. 试图通过同类对象进行删除:" + pets.remove(cymric));System.out.println("7. 对象能够精确匹配,正常删除:" + pets.remove(tmpp));System.out.println();pets.add(3, new Mouse());System.out.println("8. 借助索引进行插入:" + pets);List<Pet> sub = pets.subList(1, 4);System.out.println("9. 使用区间提取List:" + sub);System.out.println("10. 判断sub是否存在于pets中:" + pets.containsAll(sub));System.out.println();// List<Pet>没有实现Comparator接口。为方便请见,这里进行了现场实现Collections.sort(sub, new Comparator<Pet>() {@Overridepublic int compare(Pet p1, Pet p2) {return p1.toString().compareTo(p2.toString());}});System.out.println("11. 对sub进行原地排序:" + sub);System.out.println("12. containsAll()不关心顺序:" + pets.containsAll(sub));System.out.println();Random random = new Random(12);Collections.shuffle(sub, random);System.out.println("13. 通过随机数使sub进行随机排序:" + sub);System.out.println();List<Pet> copy = new ArrayList<>(pets);sub = Arrays.asList(pets.get(1), pets.get(4));System.out.println("14. 通过asList获取sub:" + sub);copy.retainAll(sub);System.out.println("15. 求交集,保留在copy和sub中都存在的元素:" + copy);System.out.println();copy = new ArrayList<>(pets);System.out.println("16. copy获得了一个pets的副本:" + copy);System.out.println();System.out.println("17. 检测pets是否为空:" + pets.isEmpty());pets.clear();System.out.println("18. pets被clear()清空:" + pets.isEmpty());System.out.println();Object[] o = copy.toArray();System.out.println("19. toArray()可以将任意Collection转换为一个数组:" + o[3]);}
}

        程序执行的结果是:

        如之前所说的,List可以在创建后添加或移除元素,而且可以自己调整大小。

        当需要查找某个元素的索引编号,或按照引用从List中删除某个元素时,都会使用到equal()方法(这个方法是Object的组成部分)。另外,每一个Pet都是一个独立的对象,这就是为什么输出5和输出6无法进行匹配的原因。

    应该意识到,List的因为会随着equal()行为的改变而改变。

        尽管插入和删除的操作需要较高的成本,但这并不意味着我们要在插入或删除时将一个ArrayList转变为LinkedList。这只意味着我们需要注意这个问题,若ArrayList执行多次插入后程序变慢,我们应该看看List的实现(可以使用分析器)。这种优化较为棘手,若不必担心可以暂时放到一边。

Iterator(迭代器)

        不管是哪种集合,都会需要通过某种方式完成元素的存取。比如List中的add()get()

        但当我们开始思考更加复杂的代码时,会发现这样一个缺点:要使用集合,编写程序时就必须考虑集合的确切类型。如果我一开始针对List编写代码,进行优化时却希望将集合修改为Set,这时就麻烦了。

        为此,就出现了迭代器(它同时也是一种设计模式)的概念。迭代器是一个对象,可以在序列中移动,并用来选择序列中的每个对象。并且使用它的程序员不需要知道序列的底层结构

    另外,迭代器是一个轻量级对象,创建成本很低。也因此,迭代器往往会具有一些使用限制。

        Java中的Iterator只能向一个方向移动,并且只能实现几个功能:

  • iterator():让Collection返回一个Iterator。此时,这个迭代器会准备好返回序列中的第一个元素。
  • next():获得序列中的下一个对象。
  • hasNext():检测序列是否存在更多对象。
  • remove():删除迭代器最近返回的元素。

        下列例子中的PetCreator().list()能够返回一个装载了随机Pet对象的ArrayList(笔者是使用了switch语句对这个方法进行了实现)

import java.util.Iterator;
import java.util.List;public class SimpleIteration {public static void main(String[] args) {// PetCreator().list()会返回一个ArrayList,其中包含随机填充的Pet对象List<Pet> pets = new PetCreator().list(12);Iterator<Pet> it = pets.iterator();while (it.hasNext()) {Pet p = it.next();System.out.print(p.id() + ":" + p + " ");}System.out.println();// 可以使用一种更简单的方式for (Pet p : pets)System.out.print(p.id() + ":" + p + " ");System.out.println();// 也可以使用迭代器来删除元素it = pets.iterator();for (int i = 0; i < 6; i++) {it.next();it.remove();}System.out.println(pets);}
}

        程序执行的结果如下:

        Iterator的存在使得程序员不再需要操心集合中的元素数量,因为使用hasNext()next()就能做到不错的处理。

    若只需要对List进行遍历,for-in语句显得更加简洁。

        这种对集合中的每个对象执行一个操作的想法十分有用,可以在许多地方发现。

        上述的例子还无法完全展示Iterator的作用,下面的例子将会创建一个与具体的集合类型无关的display()方法:

        :为了实现这一例子,自制的Pet类需要继承并实现Comparable接口。其中需要被实现的compareTo()方法就是为了进行对象排序而定义的。

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;public class CrossCollectionIteration {public static void display(Iterator<Pet> it) {while (it.hasNext()) {Pet p = it.next();System.out.print(p.id() + ":" + p + " ");}System.out.println();}public static void main(String[] args) {List<Pet> pets = new PetCreator().list(8);LinkedList<Pet> petsLL = new LinkedList<>(pets);HashSet<Pet> petsHS = new HashSet<>(pets);TreeSet<Pet> petsTS = new TreeSet<>(pets);display(pets.iterator());display(petsLL.iterator());display(petsHS.iterator());display(petsTS.iterator());}
}

        程序执行的结果如下:

        这个例子体现了Iterator真正的作用:能够将序列的遍历操作和序列的底层结构分离。也就是说,迭代器统一了对集合的访问

        Iterable接口描述了“任何可以产生一个迭代器的事物”。

使用这一接口可以将上述例子修改成更加简洁的版本:

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;public class CrossCollectionIteration2 {public static void display(Iterable<Pet> ip) {Iterator<Pet> it = ip.iterator();while (it.hasNext()) {Pet p = it.next();System.out.print(p.id() + ":" + p + " ");}System.out.println();}public static void main(String[] args) {List<Pet> pets = new PetCreator().list(8);LinkedList<Pet> petsLL = new LinkedList<>(pets);HashSet<Pet> petsHS = new HashSet<>(pets);TreeSet<Pet> petsTS = new TreeSet<>(pets);// 可以直接传入数组display(pets);display(petsLL);display(petsHS);display(petsTS);}
}

        程序执行的结果与上面的例子无异,不再重复展示。在这里,因为ArrayList已经实现了Iterable接口,所以display()方法在调用时更加方便了。

        ListIteratorIterator的一个更强大的子类型,只有List类才会生成。与Iterator不同,ListIterator可以双向移动。除此之外,它还可以生成相对于迭代器在列表中指向的当前位置的下一个和上一个元素的索引。并且可以使用set()方法替换它所访问过的最后一个元素。

import java.util.List;
import java.util.ListIterator;public class ListIteration {public static void main(String[] args) {List<Pet> pets = new PetCreator().list(8);ListIterator<Pet> it = pets.listIterator();while (it.hasNext())System.out.print(it.next() + ", " + it.nextIndex() + ", " + it.previousIndex() + ";   ");System.out.println();// 也可以进行反向的遍历while (it.hasPrevious())System.out.print(it.previous().id() + " ");System.out.println();System.out.println(pets);it = pets.listIterator(3);while (it.hasNext()) { // 从下标为3的位置开始替换对象it.next();it.set(new PetCreator().get());}System.out.println(pets);}
}

        程序执行的结果是:

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

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

相关文章

《动手学深度学习 Pytorch版》 7.4 含并行连接的网络(GoogLeNet)

import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l7.4.1 Inception块 GoogLNet 中的基本卷积块叫做 Inception 块&#xff08;大概率得名于盗梦空间&#xff09;&#xff0c;由 4 条并行路径组成。 前 3 条路径使用窗口…

MySQL数据库详解 二:数据库的高级语句(高级查询语句)

文章目录 1. 克隆表 ---- 将数据表的数据记录生成到新的表中1.1 方式一&#xff1a;先创建新表&#xff0c;再导入数据1.2 方式二&#xff1a;创建的时候同时导入 2. 清空表 ---- 删除表内的所有数据2.1 delete删除2.2 truncate删除&#xff08;重新记录&#xff09;2.3 创建临…

OSI 七层网络协议最全的图

OSI 七层网络协议最全的图 文章出处&#xff1a;https://www.shuzhiduo.com/A/RnJWawowdq/

Docker 自动化部署(保姆级教程)

Docker 自动化部署 1. jenkins 介绍1.1 参考链接&#xff1a;1.2 jenkins 概述1.3 jenkins部署项目的流程 2. jenkins 安装2.1 基于docker 镜像2.2 启动 jenkins 后端服务2.3 登录 jenkins 服务后端 3. jenkins自动化部署开始3.1 下载需要的插件3.2 创建任务3.2.1 描述3.2.2 配…

【深度学习】 Python 和 NumPy 系列教程(十八):Matplotlib详解:2、3d绘图类型(4)3D曲面图(3D Surface Plot)

目录 一、前言 二、实验环境 三、Matplotlib详解 1、2d绘图类型 2、3d绘图类型 0. 设置中文字体 1. 3D线框图&#xff08;3D Line Plot&#xff09; 2. 3D散点图&#xff08;3D Scatter Plot&#xff09; 3. 3D条形图&#xff08;3D Bar Plot&#xff09; 4. 3D曲面图…

第1篇 目标检测概述 —(1)目标检测基础知识

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。目标检测是计算机视觉领域中的一项任务&#xff0c;旨在自动识别和定位图像或视频中的特定目标&#xff0c;目标可以是人、车辆、动物、物体等。目标检测的目标是从输入图像中确定目标的位置&#xff0c;并使用边界框将其标…

程序员的快乐如此简单

最近在GitHub上发起了一个关于Beego框架的小插件的开源仓库&#xff0c;这一举动虽然看似微小&#xff0c;但其中的快乐和意义却是无法用言语表达的。 Beego是一个开源的Go语言Web框架&#xff0c;它采用了MVC架构模式&#xff0c;并集成了很多常用的功能和中间件。小插件是指…

关于POM声明为provided的依赖,运行程序时报错NoClassDefFoundError

问题叙述 我在编写flink程序时&#xff0c;将flink相关依赖声明为provided&#xff08;目的是项目打包时不会将flink依赖打入包最终jar包中&#xff0c;减少内存占用&#xff09; 但是如果在IDEA本地中执行程序会报错java.lang.NoClassDefFoundError&#xff0c;如下所示 解…

使用亚马逊云服务器在 G4 实例上运行 Android 应用程序

随着 Android 应用程序和游戏变得越来越丰富&#xff0c;其中有些甚至比 PC 上的软件更易于使用和娱乐&#xff0c;因此许多人希望能够在云上运行 Android 游戏或应用程序&#xff0c;而在 EC2 实例上运行 Android 的解决方案可以让开发人员更轻松地测试和运行 Android 应用程序…

软件测试人员必须知道的接口测试基础

一、首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能…

MySQL 学习笔记(基础)

首先解释数据库DataBase&#xff08;DB&#xff09;&#xff1a;即存储数据的仓库&#xff0c;数据经过有组织的存储 数据库管理系统DataBase Management System&#xff08;DBMS&#xff09;&#xff1a;管理数据库的软件 SQL&#xff08;Structured Query Language&#xf…

springboot整合aop,实现日志操作

前言&#xff1a; 整合之前&#xff0c;我们要明白aop是什么&#xff0c;为什么要用aop&#xff0c;aop能帮我们做什么。 答&#xff1a;AOP是面向切面编程&#xff08;Aspect-Oriented Programming&#xff09;的简称&#xff0c;它是一种编程思想&#xff0c;旨在在面向对象…

LeetCode算法二叉树—相同的树

目录 100. 相同的树 - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; 运行结果&#xff1a; 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是…

计算机组成原理之硬件的基本组成,深入介绍两大计算机结构体系,从底层出发认识计算机。

大家好&#xff0c;欢迎阅读《计算机组成原理》的系列文章&#xff0c;本系列文章主要的内容是从零学习计算机组成原理&#xff0c;内容通俗易懂&#xff0c;大家好好学习吧&#xff01;&#xff01;&#xff01; 更多的优质内容&#xff0c;请点击以下链接查看哦~~ ↓ ↓ ↓ …

苹果cms大橙子vfed 5.0去授权完美破解主题模板

大橙模版算是在苹果 cms 众多主题里&#xff0c;较为亮眼的一款了&#xff0c;主题简洁&#xff0c;功能众多&#xff0c;非常的齐全。 今天分享的就是大橙 5.0 版本模板&#xff0c;自定义菜单输入下列代码使用主题设置和资源采集。 vfed 主题设置&#xff0c;/index.php/la…

使用EasyExcel后端导出excel

官方文档&#xff1a;关于Easyexcel | Easy Excel 这里进行简单记录&#xff0c;方便确定是不是适用此方式&#xff1a; 零&#xff1a;实体类中注解用法 一&#xff1a;读excel /*** 强制读取第三个 这里不建议 index 和 name 同时用&#xff0c;要么一个对象只用index&…

Qt地铁智慧换乘系统浅学( 一 )存储站点,线路信息

存储 定义所需要的容器定义最大最小经纬度[统计站点信息 在经纬度网站](https://map.jiqrxx.com/jingweidu/)读取统计的信息存储到容器其他的一些相关函数debug 显示存储的信息更新最小最大经纬度的函数获取两点之间的距离 根据经纬度 定义所需要的容器 extern QMap<QStrin…

AI AIgents时代 - (四.) HuggingGPT MetaGPT

&#x1f7e2; HuggingGPT HuggingGPT是一个多模型调用的 Agent 框架&#xff0c;利用 ChatGPT 作为任务规划器&#xff0c;根据每个模型的描述来选择 HuggingFace 平台上可用的模型&#xff0c;最后根据模型的执行结果生成总结性的响应。 这个项目目前已在 Github 上开源&am…

获取文件创建时间

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Java源码 public void testGetFileTime() {try {String string "E://test.txt";File file new File(string);Path path file.toPath();BasicFileAttributes ba…

vscode终端中打不开conda虚拟包管理

今天&#xff0c;想着将之前鸽的Unet网络模型给实现一下&#xff0c;结果发现&#xff0c;在vscode中运行python脚本&#xff0c;显示没有这包&#xff0c;没有那包。但是在其他的ipynb中是有的&#xff0c;感觉很奇怪。我检查了一下python版本&#xff0c;发现不是我深度学习的…