模拟实现一个MyArrayList(初识泛型、包装类),List的使用(以杨辉三角为例)

本文深入探讨Java泛型的概念及应用,通过自定义MyArrayList类对比泛型前后代码优化,解析泛型类、泛型方法及包装类的使用。同时,详细介绍了List接口下ArrayList与LinkedList的常用方法,附带杨辉三角实例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、模拟实现MyArrayList

1)模拟代码及其缺陷

jdk1.5之前的版本:

class Book{}
class Person{
    public void print(){
        System.out.println("def");
    }
}
class MyArrayList{
    public MyArrayList(int capacity){
        array = new Object[capacity]; //就近原则,使用参数传进来的capacity
        size = 0;
        this.capacity = capacity;
    }
    public void add(Object e){
        //检测容量
        array[size++] = e;
    }
    public int size(){
        return size;
    }
    Object get(int index){
        //检测索引越界
        return array[index];
    }
    public boolean isEmpty(){
        return size == 0;
    }
    Object[] array;//标准库实现的各个容器任意类型都可存放所以用Object类型
    int capacity;//总大小
    int size;//有效元素个数
}
public class Test5 {
    public static void main(String[] args) {
        MyArrayList L1 = new MyArrayList(10);
        L1.add(new Person());
        L1.add(new Person());
        L1.add(new Person());
        //向下转型:不安全
        Person p = (Person)L1.get(0);
        p.print();
        MyArrayList L2 = new MyArrayList(10);
        L2.add(new Book());
        L2.add(new Book());
        L2.add(new Book());

    }
}

缺陷:
1、接收返回值时需要用户进行强制类型转化—》不方便
2、编译通过,但会发生向下转型不安全(运行时),所以引入泛型。

2)泛型

· 泛型:类型参数化
· 泛型分类:泛型类、泛型方法

class MyArratList<E>{//E是将来存储的对象的实际类型
}

· 优化后的代码:

//这里给成泛型类
class MyArrayList<E>{
    public MyArrayList(int capacity){
        array = (E[])new Object[capacity];//构造时还不知道E是什么类型,故无法直接new E[] 类型空间,只能先申请Object[]然后进行 E[]的强转
        size = 0;
        this.capacity = capacity;
    }
    public void add(E e){
        //检测容量
        array[size++] = e;
    }
    public int size(){
        return size;
    }
    E get(int index){
        //检测索引越界
        return array[index];
    }
    public boolean isEmpty(){
        return size == 0;
    }
    E[] array;
    int capacity;
    int size;
}
public class Test5 {
    public static void main(String[] args) {
        MyArrayList<Person> L1 = new MyArrayList(10);
        L1.add(new Person());
        L1.add(new Person());
        L1.add(new Person());
        Person p = L1.get(0);//
        p.print();
        MyArrayList<Book> L2 = new MyArrayList(10);
        L2.add(new Book());
        L2.add(new Book());
        L2.add(new Book());
        Book b = L2.get(2);
    }
}

· java里的泛型是伪泛型,这里的L1和L2是一个类型都是MyArratList类型。
原因是为了兼容1.5之前的代码,这里发生了类型擦除,具体行为如下图:
在这里插入图片描述
· 注意:<>内不能是基本数据类型,因为Object是所有类的基类,可以指向所有类的对象,但基本数据类型多定义的变量并不是对象。
在这里插入图片描述
若有需求,需要试用其包装类型。

3)包装类

在这里插入图片描述
· 装箱

public class Test5{
    public static void main(String[] args) {
//        ArrayList<Integer> L = new ArrayList<>();
//        L.add(10);
        int i = 10;
        Integer i1 = i;//自动装箱:编译器在编译阶段使用i构造包装类型对象,让i1引用
        Integer i2 = Integer.valueOf(i);//装箱:基础类型变量转化为对应的包装类型
        int i3 = i2.intValue();//拆箱:包装类型对应的数据拿出来
        int i4 = i1//自动拆箱:包装类型的对象直接复制给基础类型的变量
    }
}

valueOf代码实现:

  public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);//最后返回的是new出来的一个对象
    }

图解:在这里插入图片描述
· 例题:

在这里插入图片描述
解释:

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

这几自动装箱编译时调用valueOf方法,代码如上👆,我们可以看到放方法内部有一个判断,点进看到IntegerCache代码如下👇:

private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

我们看到low = -128,high = 127。
即Integer类在其内部维护了一段空间(为了提高效率从-127~128);当传进来的参数载low和high之间的话,直接返回空间里存储的对象,如果不在的话才会生成新的对象。

4)List

· List常用方法
在这里插入图片描述
· ArrayList常用方法
在这里插入图片描述
· LinkedList常用方法
在这里插入图片描述
· 练习
杨辉三角及相关知识点

public  List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new  ArrayList<>();
        for (int i = 0;i<numRows;i++){
            List<Integer> Row = new ArrayList<>();//构造时不给参数,会给一块默认容量的空空间,我的jdk版本默认空间为10
            for (int j = 0 ; j <= i ; j++) {
                if (j == 0 || j == i){
//                    Row.set(j,0);//set方法可以理解为更改的意思,要有元素才能更改。即set方法的index必须在size范围内,不然就越界了
                    Row.add(1);
                }else {
                    Row.add(0);
                }
            }
            ret.add(Row);
        }
        for (int i = 2; i < numRows; ++i) {
            List<Integer> cur = ret.get(i);
            List<Integer> pre = ret.get(i-1);
            for (int j = 1; j < i; ++j) {
                cur.set(j,pre.get(j)+pre.get(j-1));
            }
        }
        return ret;
    }

注意看本文代码中的注释哦~
加油鸭!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值