当前位置: 首页 > news >正文

数据结构预备知识

目录

1. 什么是集合框架

2. 什么是数据结构

3. 容器背后对应的数据结构

4. 相关java知识

5. 时间复杂度

6. 空间复杂度

7. 包装类

7.1 装箱和拆箱

7.2 阿里面试题:

8. 泛型

8.1 泛型的语法

8.2 泛型怎样编译

9. 泛型的上界

9.1 语法

9.2 泛型方法


1. 什么是集合框架

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

主要表现为将多个元素element置于一个单元中,用于对这些元素进行快速、便捷的存储store、检索retrieve、管理manipulate,即我们俗称的增删改查CEUD

2. 什么是数据结构

数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合

3. 容器背后对应的数据结构

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

Collection:是一个接口,包含大部分容器常用的一些方法

List:是一个接口,规范了ArrayList和LinkedList中要实现的方法

  • ArrayList:实现了List接口,底层为动态类型顺序表
  • LinkedList:实现了List接口,底层为双向链表

Stack:底层是栈,栈是一种特殊的顺序表

Queue:底层是队列,队列是一种特殊的顺序表

Deque:是一个接口

Set:集合,是一个接口,里面放置的是K模型

  • HashSet:底层为哈希桶
  • TreeSet:底层为红黑树

Map:映射,里面存储的是K-V模型的键值对

  • HashMap:底层为哈希桶
  • TreeMap:底层为红黑树

4. 相关java知识

  1. 泛型Generic
  2. 自动装箱autobox和自动拆箱autounbox
  3. Object的equals方法
  4. Comparable和Comparator接口

5. 时间复杂度

大O符号:是用于描述函数渐进行为的数学符号

推导大O阶方法:

  1. 用常数1取代运行时间中的所有加法常数
  2. 在修改后的运行次数函数中,只保留最高阶项
  3. 如果最高阶项存在且不是1,则去除与这个项目相乘的常数

平常所说的时间复杂度和空间复杂度都是指最坏情况下

注意:结合算法思想,不能只看代码

冒泡排序的时间复杂度:O (n^2)(一开始就是倒序的),最好是O(n)(一开始就是有序的)

二分查找的时间复杂度:O(logn)

阶乘递归的时间复杂度:O(n)

斐波那契递归的时间复杂度:O(2^n)

6. 空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。空间复杂度不是程序占用了多少bytes的空间,而是变量的个数。与时间复杂度一样,也使用大O渐进表示法

冒泡排序的空间复杂度:O(1)

阶乘递归的空间复杂度:O(n)

常遇到的复杂度:

O(1)<O(logN)<O(N)<O(N*logN)<O(N^2)

7. 包装类

在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型

7.1 装箱和拆箱

装箱:把基本数据类型变为包装类类型的过程

public class Test {public static void main(String[] args) {int a = 10;Integer i = Integer.valueOf(a);//显式装箱Integer i2 = 10;//自动装箱(隐式装箱,底层调用了Integer.valueOf方法)Double d = Double.valueOf(a);}
}

拆箱:把包装类类型变为基本数据类型的过程

public class Test {public static void main(String[] args) {Integer a = 10;int b = a;//自动拆箱int c = a.intValue();//显式、手动double d = a.doubleValue();}
}

使用javap -c在cmd中(找到该段代码的文件位置然后输入cmd)可以查看底层代码实现

7.2 阿里面试题:
public class Test {public static void main(String[] args) {Integer a = 100;Integer b = 100;System.out.println(a == b);//trueInteger c = 200;Integer d = 200;System.out.println(c == d);//false}
}

分析:

装箱的操作:

    @IntrinsicCandidatepublic static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

上述代码中的 i 应该在一个范围的时候直接返回数组中的值,否则返回新的对象

用等号比较,必然不一样。

i 的范围:-128~127(共256个数字,在cache缓存中)

8. 泛型

一般的类和方法,只能使用具体的类型:基本类型或自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。——《Java编程思想》

泛型,通俗讲:就是适用于许多许多类型;从代码上将:对类型实现了参数化

class MyArray{public Object[] array=new Object[10];public void setValue(int index,Object value){array[index]=value;}public Object getValue(int index){return array[index];}
}
public class Test {public static void main(String[] args) {MyArray myArray=new MyArray();myArray.setValue(0,10);myArray.setValue(1,"hello");String str=(String)myArray.getValue(1);System.out.println(str);//hello}
}

以上代码存在一些问题:

  1. 存放数据太乱,什么类型都能放
  2. 每次获取数据时,都要进行强转

泛型可以解决,泛型的主要目的:指定当前的容器,要持有什么类型的对象,让编译器去检查。此时,要把类型作为参数传递,需要什么类型,就传入什么类型。

8.1 泛型的语法
class 泛型类名称<类型形参列表>{//这里可以使用类型参数
}
class MyArray<E>{//<E>占位符表示一个泛型public Object[] array=new Object[10];public void setValue(int index,E value){array[index]=value;}public E getValue(int index){return (E)array[index];}
}
public class Test {public static void main(String[] args) {MyArray<Integer> myArray=new MyArray<Integer>();myArray.setValue(0,10);
//        myArray.setValue(1,"hello");//自动类型检查Integer value=myArray.getValue(0);//自动类的转换System.out.println(value);//10MyArray<String> myarray=new MyArray<>();//可以省略类型实参的填写myarray.setValue(0,"hello");String value1=myarray.getValue(0);System.out.println(value1);//hello}
}

了解:【规范】类型形参一般使用一个大写字母表示,常用名称有:

E表示Element,K表示Key,V表示Value,N表示Number,T表示Type

<>中只能写类类型,不能写简单类型(编译不能通过)

裸类型是一个泛型类但没有带着类型实参,例如:

MyArray list=new MyArray();

注意:我们不要自己去使用裸类型,裸类型是为了兼容老版本的API保留的机制

8.2 泛型怎样编译

泛型是编译时期的一种机制,在运行的时候没有泛型的概念【JVM中没有泛型的概念】

在编译的过程中,将所有的E替换为Object这种机制,称之为:擦除机制

class MyArray<E> {//<E>占位符表示一个泛型public Object[] array = new Object[10];public void setValue(int index, E value) {array[index] = value;}public E getValue(int index) {return (E) array[index];}
}public class Test {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();MyArray<Integer> myArray2 = new MyArray<>();Test test = new Test();System.out.println(myArray);//MyArray@3b07d329System.out.println(myArray2);//MyArray@41629346System.out.println(test);//Test@404b9385}
}

9. 泛型的上界

在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束

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

例如:

public class MyArray<E extends Number>{...
}

没有指定类型边界的E,可以视为E extends Object

复杂实例:

public class MyArray<E extends Comparable<E>>{...
}

E必须是实现了Comparable接口的

class Alg<E extends Comparable<E>> {public E findMax(E[] arr) {E max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i].compareTo(max) > 0) {max = arr[i];}}return max;}
}class Person implements Comparable<Person> {@Overridepublic int compareTo(Person o) {return 0;}
}public class Test {public static void main(String[] args) {Alg<Integer> alg = new Alg<>();System.out.println(alg.findMax(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));//10Alg<Person> alg1 = new Alg<>();System.out.println(alg1.findMax(new Person[]{new Person()}));//Person@41629346}
}
9.2 泛型方法
class Alg {public<E extends Comparable<E>> E findMax(E[] arr) {E max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i].compareTo(max) > 0) {max = arr[i];}}return max;}
}public class Test {public static void main(String[] args) {Alg alg = new Alg();Integer[] arr = {1,2,3,4,5,6};int ret=alg.findMax(arr);System.out.println(ret);//6}
}

静态泛型方法:

class Alg {public static <E extends Comparable<E>> E findMax(E[] arr) {E max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i].compareTo(max) > 0) {max = arr[i];}}return max;}
}public class Test {public static void main(String[] args) {Integer[] arr = {1, 2, 3, 4, 5, 6};System.out.println(Alg.findMax(arr));//6}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 链表反转算法
  • 12.2 使用prometheus-sdk向pushgateway打点
  • Unity编辑器扩展:创建一个欢迎窗口,在启动Editor的时候显示自定义窗口。
  • 【信息学奥赛一本通】1008:计算(a+b)/c的值
  • easypoi模板导出word多页导出加强版
  • 5 分钟 Stable Diffusion 本地安装指南
  • Android14 蓝牙设备类型修改
  • 本地Docker部署Navidrome音乐服务器与远程访问听歌详细教程
  • 根据状态的不同,显示不同的背景颜色
  • 数据库学习
  • 动手实现基于Reactor模型的高并发Web服务器(一):epoll+多线程版本
  • 制作docker镜像
  • 打卡51天------图论(深搜/广搜应用题)
  • OpenCV图像滤波(Image Filtering)常用函数及其用法详解
  • CART决策树-基尼指数(全网最详解)
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • Angular6错误 Service: No provider for Renderer2
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Go 语言编译器的 //go: 详解
  • gops —— Go 程序诊断分析工具
  • js对象的深浅拷贝
  • Linux中的硬链接与软链接
  • MySQL用户中的%到底包不包括localhost?
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • 包装类对象
  • 关于字符编码你应该知道的事情
  • 技术发展面试
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 前端js -- this指向总结。
  • 前端相关框架总和
  • 前端性能优化——回流与重绘
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 系统认识JavaScript正则表达式
  • 正则与JS中的正则
  • 走向全栈之MongoDB的使用
  • NLPIR智能语义技术让大数据挖掘更简单
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #define,static,const,三种常量的区别
  • #mysql 8.0 踩坑日记
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (floyd+补集) poj 3275
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (八)c52学习之旅-中断实验
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (含笔试题)深度解析数据在内存中的存储
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (利用IDEA+Maven)定制属于自己的jar包
  • (十)T检验-第一部分
  • (十三)Flask之特殊装饰器详解
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • ***通过什么方式***网吧
  • .apk文件,IIS不支持下载解决