java数据结构前置知识以及认识泛型

目录

什么是集合框架

容器

时间复杂度

空间复杂度

包装类

装箱

拆箱

引出泛型

泛型类的使用

类型推导

泛型如何编译的

泛型的上界

泛型方法静态泛型方法以及泛型上界


什么是集合框架

Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces和其实现类 classes 。

如何理解这张图?

所有的这些从某种意义上说都实现了Iterable这个接口,然后collection继承extends了它也可以说拓展了它这个接口相当于collection这个接口具备了Iterable这个接口的功能,相当于这个接口定义的类型可以引用下面具体的对象,例如List list=new ArrayList()暂且这样写,后面同样一个道理

这张图描述了java当中 类与类 类与接口之间的关系

说明:java的集合类和关系不一定只有上图,上图只是描述了部分重要的常见的类


容器

每个容器其实都是对某种特定数据结构的封装

1. Collection 是一个接口,包含了大部分容器常用的一些方法
2. List 是一个接口,规范了 ArrayList LinkedList 中要实现的方法
ArrayList 实现了 List 接口,底层为动态类型顺序表
LinkedList :实现了 List 接口,底层为双向链表
3. Stack :底层是栈,栈是一种特殊的顺序表
4. Queue :底层是队列,队列是一种特殊的顺序表
5. Deque :是一个接口
6. Set :集合,是一个接口,里面放置的是 K 模型
HashSet :底层为哈希桶,查询的时间复杂度为 O(1)
TreeSet :底层为红黑树,查询的时间复杂度为 O(
), 关于 key 有序的
7. Map :映射,里面存储的是 K-V 模型的键值对
HashMap :底层为哈希桶,查询时间复杂度为 O(1)
TreeMap :底层为红黑树,查询的时间复杂度为 O(
) ,关于 key 有序


时间复杂度

时间效率被称为时间复杂度,算法中的基本操作的执行次数一般找执行语句最多的,为算法的时间复杂度

大O的渐进表示法:

用法例子:

// 请计算一下func1基本操作执行了多少次?void func1(int N){int count = 0;for (int i = 0; i < N ; i++) {for (int j = 0; j < N ; j++) {count++;
}
}for (int k = 0; k < 2 * N ; k++) {count++;
}int M = 10;while ((M--) > 0) {count++;
}System.out.println(count);
}

只需要大概执行次数,那么这里我们使用大O的渐进表示法

满足三点:

1、用常数1取代运行时间中的所有加法常数

2、在修改后的运行次数函数中,只保留最高阶项

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)


空间复杂度

而空间效率被称作空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少 bytes 的空 间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也 使用大 O 渐进表示法。
用法例子:
/ 计算bubbleSort的空间复杂度?
void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) {boolean sorted = true;for (int i = 1; i < end; i++) {if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;
}
}if (sorted == true) {break;
}
}
}

注意

如果算法中使用了固定数量的额外变量或数组,不随输入规模的增加而变化,则空间复杂度是O(1)。

如果算法使用了和输入规模相关的额外空间,比如创建了一个大小与输入规模相等的数组来存储结果,那么空间复杂度通常是 O(N)。

对于递归算法,需要考虑递归调用所使用的栈空间。

每次递归调用都会占用一定的栈空间,因此递归算法的空间复杂度通常是 O(N) 或者 O(log N),取决于递归调用的深度


包装类

Java 中,由于基本类型不是继承自 Object ,为了在泛型代码中可以支持基本类型, Java 给每个基本类型都对应了 一个包装类型
基本数据类型 包装类
byte       Byte
short      Short
int        Integer
long       Long
float      Float
double     Double
char       Character
boolean    Boolean

装箱

public static void main1(String[] args) {//装箱/装包:把一个 基本数据类型 转变为 包装类型Integer a = 10;// 隐式装箱/自动装箱int i = 99;Integer b = i;System.out.println(b);Integer aa = Integer.valueOf(10);//显示装箱System.out.println(aa);}
}

拆箱

  public static void main2(String[] args) {//拆箱/拆包:把一个 包装类型 转变为 基本数据类型Integer a = 66;int b = a;//自动拆箱System.out.println(b);int aa = a.intValue();//显示拆箱double d = a.doubleValue();//拆成double类型}


下列代码输出什么,为什么?
public class Test {public static void main(String[] args) {Integer a = 100;Integer b = 100;System.out.println(a == b);Integer a1 = 200;Integer b1 = 200;System.out.println(a1 == b1);}

解释如下:

Java 中的 Integer 类在范围为 [-128, 127] 内的整数上具有缓存功能,即当创建一个范围内的 Integer 对象时,会从缓存中获取已经存在的对象而不是新创建一个对象。这是因为在此范围内的整数被频繁使用,因此缓存可以提高性能和节省内存。

但是,当整数超出范围 [-128, 127] 时,每次创建的 Integer 对象都会是一个新的对象,因此这些对象的地址不同,即使它们的值相同。因此,对于超出范围的整数,使用 == 比较两个 Integer 对象时,结果通常会是 false。

结果:

a 和 b 的值都在范围内,因此它们的地址相同,a == b 返回 true。
c 和 d 的值超出范围,因此它们的地址不同,c == d 返回 false。


引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法
返回数组中某个 下标的值?
泛型语法例子:
/*** @param <T> 代表当前类 是一个 泛型类,<T>是一个占位符*/
class MyArray<T> {//public T[] array = (T[]) new Object[10];public Object[] array = new Object[10];public void setValue(int pos, T val) {this.array[pos] = val;}public T getValue(int pos) {return (T) array[pos];//把返回类型 强转为指定类型}}public class Test2 {public static void main(String[] args) {//泛型其实就是将 类型 进行 传递MyArray<Integer> myArray = new MyArray<>();myArray.setValue(1, 10);System.out.println(myArray.getValue(1));MyArray<String> myArray1 = new MyArray<>();myArray1.setValue(0, "hello");System.out.println(myArray1.getValue(0));}
}
以上代码实现后 发现 任何类型数据都可以存放
1. 类名后的 <T> 代表占位符,表示当前类是一个泛型类
注意【规范】类型形参一般使用一个大写字母表示,常用的名称有:
2.不能new泛型类型的数组
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类 型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型

泛型类的使用

例子:
MyArray<Integer> list = new MyArray<Integer>();
注意:泛型只能接受类,所有的基本数据类型必须使用包装类!
类型推导
例子:
MyArray<Integer> list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer
小结:
1. 泛型是将数据类型参数化,进行传递
2. 使用 <T> 表示当前类是一个泛型类。
3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

泛型如何编译的

擦除机制

通过命令:javap -c 查看字节码文件,所有的T都是Object

在编译的过程当中,将所有的 T 替换为 Object 这种机制,我们称为: 擦除机制
Java 的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息

泛型的上界

语法:
class 泛型类名称<类型形参 extends 类型边界> {
...
}

例子:

public class MyArray<E extends Number> {
...
}
上述例子表示只接受 Number 的子类型作为 E 的类型实参
MyArray<Integer> l1; // 正常,因为 Integer 是 Number 的子类型
MyArray<String> l2; // 编译错误,因为 String 不是 Number 的子类型

泛型方法静态泛型方法以及泛型上界

定义语法:

方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }
例子:
class Person1 implements Comparable<Person1> {@Overridepublic int compareTo(Person1 o) {return 0;}
}//泛型类
//T一定是实现了Comparable这个接口
class A<T extends Comparable<T>> {//将来你指定这个A泛型类传入的类型参数一定是实现了Comparable这个接口public T findMax(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if (max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}//泛型方法
class B {public <T extends Comparable<T>> T findMax(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if (max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}//静态泛型方法
class B1 {public static <T extends Comparable<T>> T findMax(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if (max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}public class Test4 {public static void main(String[] args) {//静态泛型方法Integer[] integers2 = {1, 2, 3, 4};Integer integer3 = B1.findMax(integers2);System.out.println(integer3);//泛型方法B b = new B();Integer[] integers1 = {1, 2, 3, 4};//类型推导:根据实参传值 来推导 此时的类型Integer integer1 = b.findMax(integers1);//两种写法Integer integer2 = b.<Integer>findMax(integers1);//两种写法,这个全一点,可以省略System.out.println(integer1);//泛型类A<Integer> a = new A<>();Integer[] integers = {1, 2, 3, 4};Integer integer = a.findMax(integers);System.out.println(integer);A<Person1> a1 = new A<>();}
}

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

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

相关文章

普通男孩的新年创作纪念日

前言 首先在新春佳节&#xff0c;小编在这里祝各位大佬。萌新友友们新年好&#xff0c;希望每一个烟火般的你在新的一年里 offer 多多&#xff0c;薪资多多 &#xff0c;龙行龘龘 &#x1f409; &#x1f409; &#x1f409; &#x1f409;&#xff0c;前程朤朤 ❤️ ❤️ ❤…

学习天机02

1.注入bean的写法 构造函数的注入 2.回答和评论 在做这个功能的时候需要理解一些概念&#xff0c;张三提出问题就是提问者&#xff0c;李四去回答张三的问题&#xff0c;李四就是回答者&#xff0c;王五去回答李四的评论&#xff0c;王五就是评论者。 在提供的InteractionRep…

通俗易懂搞定forEach和map的区别和使用

前言 在前端开发的时候&#xff0c;我们有时候需要对后端传过来的数组的进行相应的遍历处理&#xff0c;但是很多小伙伴对map和forEach两个方法的界限还是有模糊&#xff0c;本文从具体的示例来弄清楚两者的相同点和不同点 相同点 1.都是用于遍历数组的方法&#xff0c;可以…

《Linux 简易速速上手小册》第1章: Linux 系统基础(2024 最新版)

文章目录 1.1 Linux 操作系统概述1.1.1 重点基础知识1.1.2 重点案例&#xff1a;配置 Apache Web 服务器1.1.3 拓展案例 1&#xff1a;配置 SSH 服务以进行远程管理1.1.4 拓展案例 2&#xff1a;使用 Cron 定时任务 1.2 选择合适的 Linux 发行版1.2.1 重点基础知识1.2.2 重点案…

腾讯云幻兽帕鲁服务器配置怎么选择合适?

腾讯云幻兽帕鲁服务器配置怎么选&#xff1f;根据玩家数量选择CPU内存配置&#xff0c;4到8人选择4核16G、10到20人玩家选择8核32G、2到4人选择4核8G、32人选择16核64G配置&#xff0c;腾讯云百科txybk.com来详细说下腾讯云幻兽帕鲁专用服务器CPU内存带宽配置选择方法&#xff…

理解JAVA命名和目录接口(JNDI)

理解JAVA命名和目录接口(JNDI) 考虑访问网站的场景,Web用户要求记住四字节的IP地址而不是有意义的名称。例如,假设Web用户用123.23.3.123而不是hotmail.com访问hotmail网站。在这种情形下,Web用户难以记住不同的IP地址来访问不同的网站。因此,要使其变得对Web用户简单方…

Vue3高频知识点和写法

一 Vue插件 二 vue3项目创建 创建完成后npm install npm run dev 三 setup 一 响应式数据 setup函数是用来代替data和methods的写法的&#xff0c;在setup函数中声明的数据和函数&#xff0c;导出后可以在页面中使用。 但是暂时不是响应式数据&#xff0c;如果要响应式数据的…

单片机学习笔记---AT24C02数据存储

目录 AT24C02数据存储 准备工作 代码讲解 I2C.c 模拟起始位置的时序 模拟发送一个字节的时序 模拟接收应答的时序 模拟接收一个字节的时序 模拟发送应答的时序 模拟结束位置的时序 I2C.h AT24C02.c 字节写&#xff1a;在WORD ADDRESS&#xff08;字地址&#xff…

Verilog刷题笔记29

题目&#xff1a; Create a 100-bit binary ripple-carry adder by instantiating 100 full adders. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out. To encourage you to actually instantiate full adders, also output the ca…

【教3妹学编程-算法题】输入单词需要的最少按键次数 I

3妹&#xff1a;2哥&#xff0c;新年好鸭~ 2哥 : 新年好&#xff0c;3妹这么早啊 3妹&#xff1a;是啊&#xff0c;新年第一天要起早&#xff0c;这样就可以起早一整年 2哥 :得&#xff0c;我还不了解你&#xff0c;每天晒到日上三竿 3妹&#xff1a;嘿嘿嘿嘿&#xff0c;一年是…

【数据结构】链表OJ面试题4《返回链表入环的第一个结点》(题库+解析)

1.前言 前五题在这http://t.csdnimg.cn/UeggB 后三题在这http://t.csdnimg.cn/gbohQ 给定一个链表&#xff0c;判断链表中是否有环。http://t.csdnimg.cn/Rcdyc 记录每天的刷题&#xff0c;继续坚持&#xff01; 2.OJ题目训练 10. 给定一个链表&#xff0c;返回链表开始…

TCP和UDP相关问题(重点)——8.TCP的拥塞控制怎么实现的?

在某段时间内&#xff0c;若对网络中某一资源的需求超过了该资源所能提供的可用部分&#xff0c;网络性能就会变坏&#xff0c;比如在高速公路上行驶的车辆&#xff0c;如果一时期内涌入了太多的车辆&#xff0c;道路将变得拥堵&#xff0c;交通状况变差。网络中也是一样&#…