数据结构的基本框架以及泛型

目录

集合框架

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

interface: 接口

abstracb class: 抽象类

class: 类

这一张图片里面.,描述了Java里面,比较重要的类与类, 类与接口之间的关系.

在这两个图里面,最重要的接口有4个,分别是list, queue,set 以及 map,其他的类都是实现这些接口的

复杂度

在我们写代码的时候,我们是会讲究一个效率问题的,被用复杂度来表示,其中也分为时间复杂度以及空间复杂度,这两个复杂度都是用: 大O的渐进表示法来表示的

复杂度肯定也是有分为最好情况,最坏情况以及平均情况的 ,但是我们一般在讨论的时候,我们都是要默认说最坏的情况.

大O的渐进表示法

1>用常数 1 取代时间中的所有加法常数

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

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

例如:

例如代码之中有这样一块循环,复杂度是按照最坏的情况考虑的,

复制代码
for (int i = 0; i < N; i++) {
       for (int j = 0; j < N; j++) {
             count++;
        }
}

首先里面第一部分是这样一块代码,两个for循环套在一起,最坏的情况就是每个for会循环N次,所以这一块的复杂度就是N^2次

复制代码
for (int i = 0; i < 2 * N; i++) {
           count++;
       }

第二部分里面,循环会有2N次,所以他的复杂度就是2N次

复制代码
int m = 10;
        while ((m--) > 0){
            count++;
        }

第三部分就是一个while循环,可以看见m是10,所以这个循环最多进行10次,复杂度为10

最后的话我们就可以知道这个复杂度是O(N) = N^2 + 2 * N + 10

我们再根据大O的渐进法进行化简,O(N) = N^2就是代码的复杂度了

装包(箱)或者拆包(箱)

装包

复制代码
Integer a =10;

int i = 5;
Integer b =i;

上面的代码是两种装包的写法

但是我们有两种装包的方式,一种是显式,一种是隐式装包

复制代码
Integer a =10;
Integer aa = Integer.valueOf(10);

上面这两个就是不用的装包方式,a是一种隐式装包,在写的时候把valueof给隐藏起来了,没有显式出来

aa的话就是显式装包,在这个过程中,把valuof这个过程给写了出来

拆包

同样的,拆包也分为隐式的和显式的

复制代码
Integer a =10;
int i = a;

想这个就是隐式的拆包

复制代码
int aa = a.intValue();
double d = a.doubleValue();

像上面这两个就是显式的拆包,

从上面可以看出,对于拆包来说,隐式和显式的差别也就是在于value的差别

在这个截图上面,我们可以看出,定义了两组不同的包装类.但是有一组返回的是true,有一组返回的是false,这是为什么呢?

通过上面两个截图,调用valueof的底层源码可以看到,它的取值范围是在-128到127之间的,那也就是说我们的aa,以及bb是超出了这个范围的.

所以当aa,bb都取值200时候,他们都是创建了新的地址,所以地址是不同的

泛型

泛型的概念: 实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据.也可以根据成员方法数组中某个下标的值

复制代码
class MyArray<T>{
    public Object[] array = new Object[10];
    public void setvalue(int pos,T val){
        array[pos] = val;
    }
    public T getvalue(int pos){
        return (T)array[pos];
    }
}
public class Test {
    public static void main(String[] args) {
        MyArray<Integer> myArray = new MyArray<Integer>();
        myArray.setvalue(0,10);
        myArray.setvalue(1,100);
        int a = myArray.getvalue(1);
        System.out.println(a);


        
        MyArray<String> myArray1 = new MyArray<String>();
        myArray1.setvalue(0,"hello");
        myArray1.setvalue(1,"ko");
        String b = myArray1.getvalue(0);
        System.out.println(b);

像在上面就是个泛型的代码,在上面这个代码里面,我们可以发现,我们在输出的时候可以输出整数,也可以输出字符串,我们想输出其他的类型,只要创建一个新的对象就可以了

我们可以正常的输出a和b,就像泛型的概念说的"类中包含一个数组成员,使得数组中可以存放任何类型的数据"

像在泛型里面还要一点要注意

像我们在泛型里面创建对象的时候,我们不可以new一个泛型类型的数据,必须是Object类型的,因为泛型是在编译时期的一个概念,当程序运行起来到了JVM以后,就没有了泛型的概念

泛型在编译时期是如何编译的?

是采用了擦除机制,把T擦除成了Object!!!

泛型的上界

模板: class 泛型类名称 <类型形参 extends 类型边界> {

...

}

复制代码
class TestGeneric<T extends Number>{
    
}

public class Test {
    public static void main(String[] args) {
        TestGeneric<Number> testGeneric = new TestGeneric<>();
        
    }
}

这上面就是泛型的一个使用模板

这上面的话是一个泛型取最大值的方法,但是我们可以看到在if的那个地方,会报错.

这是因为T一定是引用数据类型,最终被擦除为了Object类型,因为我们是要求最大值,所以这个T的类型一定是可比较的,所以我们要继承自Comparable接口,然后可以调用CompareTo进行比较

所以正确的我们if里面要像上图这样写才可以

复制代码
class Alg<T extends Comparable<T>> {
    public T findMaxValue(T[] array) {
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if (max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}


public class Test {
    public static void main(String[] args) {
        Alg<Integer> alg = new Alg<>();
        Integer[] integers = {1, 2, 3, 4, 5, 6, 7};
        Integer ret = alg.findMaxValue(integers);
        System.out.println(ret);
    }
}

完整的代码就是上面这样的,最大值也就是7

泛型方法求最大值

复制代码
class Alg2{
    public static <T extends Comparable<T>> T findMaxValue(T[] array){
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if (max.compareTo(array[i]) < 0){
                max = array[i];
            }
        }
        return max;
    }
}
public class Test {
    public static void main(String[] args) {
        Alg2 alg2 = new Alg2();
        Integer[] integers1 = {1,2,3,4,5,6,7};
        Integer ret1 = alg2.findMaxValue(integers1);
        System.out.println(ret1);
    }
 }

像上面这个方法的话,我们的Alg2里面,并没有写是什么类型的,但是为什么会知道现在是什么类型的呢,因为类型推导

会根据我们类型的传值,来推到此时的类型

相关推荐
健康的猪2 分钟前
golang的cgo的一点小心得
开发语言·后端·golang
冰茶_7 分钟前
.NET MAUI 发展历程:从 Xamarin 到现代跨平台应用开发框架
学习·microsoft·微软·c#·.net·xamarin
祁同伟.12 分钟前
【数据结构 · 初阶】- 堆的实现
c语言·数据结构
echo17542518 分钟前
Apipost免费版、企业版和私有化部署详解
java
夜夜敲码24 分钟前
C语言教程(十六): C 语言字符串详解
c语言·开发语言
帅云毅26 分钟前
Web3.0的认知补充(去中心化)
笔记·学习·web3·去中心化·区块链
豆豆26 分钟前
day32 学习笔记
图像处理·笔记·opencv·学习·计算机视觉
宋康31 分钟前
C语言结构体和union内存对齐
c语言·开发语言
逢生博客36 分钟前
使用 Python 项目管理工具 uv 快速创建 MCP 服务(Cherry Studio、Trae 添加 MCP 服务)
python·sqlite·uv·deepseek·trae·cherry studio·mcp服务
异常君36 分钟前
Java 高并发编程:等值判断的隐患与如何精确控制线程状态
java·后端·代码规范