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

一、模拟实现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;
    }

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用泛型实现的MyArrayList类的示例代码: ```java public class MyArrayList<E> { private static final int DEFAULT_CAPACITY = 10; private int size; private E[] elements; public MyArrayList() { elements = (E[]) new Object[DEFAULT_CAPACITY]; } public MyArrayList(int capacity) { elements = (E[]) new Object[capacity]; } public void add(E e) { if (size == elements.length) { resize(); } elements[size++] = e; } public E get(int index) { checkIndex(index); return elements[index]; } public void set(int index, E e) { checkIndex(index); elements[index] = e; } public E remove(int index) { checkIndex(index); E element = elements[index]; for (int i = index; i < size - 1; i++) { elements[i] = elements[i + 1]; } elements[--size] = null; return element; } public boolean contains(E e) { for (int i = 0; i < size; i++) { if (elements[i].equals(e)) { return true; } } return false; } public int size() { return size; } public boolean isEmpty() { return size == 0; } private void resize() { E[] newElements = (E[]) new Object[elements.length * 2]; System.arraycopy(elements, 0, newElements, 0, size); elements = newElements; } private void checkIndex(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); } } } ``` 使用示例: ```java MyArrayList<String> list = new MyArrayList<>(); list.add("hello"); list.add("world"); System.out.println(list.get(0)); // output: hello list.set(1, "java"); System.out.println(list.get(1)); // output: java System.out.println(list.remove(0)); // output: hello System.out.println(list.contains("java")); // output: true System.out.println(list.size()); // output: 1 System.out.println(list.isEmpty()); // output: false ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值