程序员

身为java开发人员,这份Java泛型与容器知识点整理你真得好好

2020-07-28  本文已影响0人  程序员伟杰

容器框架图:

Collection接口

Set接口:Collection的子接口>>无序不可重复
HashSet:Set接口的实现类

List接口:Collection的子接口>>有序可重复

ArrayList:Lis接口t的实现类(数组列表)查询效率高
LinkedList:List接口的实现类(链表)增删效率高
Vector:List接口的实现类(底层是数组)线程安全

Map接口

HashMap:Map接口的实现类

Collection< E >接口常用方法

下面的方法一般用于2个容器间的操作;不过也可以使用1个容器,自己与自己进行交、并、差等操作,一般没这个必要。
注意:2个容器的数据类型必须一致


代码测验如下:

import java.util.ArrayList;
import java.util.Collection;

public class TestCollection {
    
    public static void main(String[] args) {
        
        Collection<String> coll = new ArrayList<>();        
        coll.add("1");
        coll.add("2");
        coll.add("3");
        System.out.println(coll);//[1, 2, 3]
        coll.clear();
        System.out.println(coll);//[]
        
        coll.add("A");
        coll.add("B");
        coll.add("C");
        coll.add("DE");
        System.out.println(coll);//[A, B, C, DE]
        
//      coll.remove(2);//这里表示的含义是移除整数2,而不是移除数组下标为2的元素
        coll.remove("DE");
        System.out.println(coll);//[A, B, C]
        
        int a = coll.size();
        System.out.println(a);//3
        
        boolean b = coll.isEmpty();
        System.out.println(b);//false
        
        boolean c = coll.contains("A");
        System.out.println(c);//true
        
        Object[] d = coll.toArray();
        System.out.println(d);//[Ljava.lang.Object;@15db9742
        
        System.out.println("=========================================");
        
        Collection<String> coll02 = new ArrayList<>();
        coll02.add("B");
        coll02.add("C");
        coll02.add("D");
        System.out.println("coll:"+coll);//coll:[A, B, C]
        System.out.println("coll02:"+coll02);//coll02:[B, C, D]
        
        boolean e = coll.containsAll(coll02);
        System.out.println(e);//false
        
        coll.retainAll(coll02);
        System.out.println(coll);//[B, C]
        
        coll.addAll(coll02);
        System.out.println(coll);//[B, C, B, C, D]
        
        coll.removeAll(coll02);
        System.out.println(coll);//[]
        
    }
    
}

List< E >接口常用方法

代码测验如下:

import java.util.ArrayList;
import java.util.List;
/**
 *  List接口中的方法多加了一个索引、下标
 */
public class TestList {
    
    public static void main(String[] args) {
        
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);//[1, 2, 3, 4, 5]
        
        list.add(1,11);
        System.out.println(list);//[1, 11, 2, 3, 4, 5]
        
//      list.remove(11);//此处默认将11当成下标来运算,而不是将11当成一个元素内容
        
        list.remove(1);
        System.out.println(list);//[1, 2, 3, 4, 5]
        
        list.set(0,11);
        System.out.println(list);//[11, 2, 3, 4, 5]
        
        int a = list.get(0);
        System.out.println(a);//11
        
        list.add(5);
        list.add(4);
        list.add(3);
        list.add(2);
        list.add(11);
        
        int b = list.indexOf(11);
        System.out.println(b);//0
        
        int c = list.lastIndexOf(11);
        System.out.println(c);//9
        
        List<Integer> list02 = new ArrayList<>();
        list02.add(12);
        list02.add(14);
        list02.add(16);
        
        list.addAll(1,list02);
        System.out.println(list);//[11, 12, 14, 16, 2, 3, 4, 5, 5, 4, 3, 2, 11]
            
    }
    
}

区分Collection接口中的remove方法、List接口中的remove方法

import java.util.ArrayList;
import java.util.List;
/**
 *  区分Collection接口中的remove方法、List接口中的remove方法
 *  
 */
public class TestRemove {
    
    public static void main(String[] args) {
        
        List<String> list01 = new ArrayList<>();
        list01.add("1");
        list01.add("2");
        list01.add("3");
        list01.add("4");
        list01.add("5");
        System.out.println(list01);//[1, 2, 3, 4, 5]
        
        //父接口Collection中的remove方法
        list01.remove("1");
        System.out.println(list01);//[2, 3, 4, 5]
        
        //List接口中的remove方法
        list01.remove(1);
        System.out.println(list01);//[2, 4, 5]
        
        System.out.println("=========================================");
        
        List<Integer> list02 = new ArrayList<>();
        list02.add(1);
        list02.add(2);
        list02.add(3);
        list02.add(4);
        list02.add(5);
        list02.add(11);
        
        list02.remove(1);
        System.out.println(list02);//[1, 3, 4, 5, 11]
        
        /**
         * java.lang.IndexOutOfBoundsException: Index: 11, Size: 5
         */
        list02.remove(11);//此处会报下表越界异常,因为在int类型中它默认指的是下标索引
        
    }
    
}

练习一:手写模拟ArrayList创建数组,添加元素功能(加入泛型):

/**
 *  手写ArrayList创建容器,添加元素功能
 *  增加泛型
 */
public class WriteArrayList<E> {
    
    private Object[] array;
    private int size;//数组下标
    private static final int DEFAULT = 10;
    
    public WriteArrayList() {
        array = new Object[DEFAULT];
    }
    
    public WriteArrayList(int index) {
        array = new Object[index];
    }
    
    public void add(E data) {
        array[size++] = data;
    }
    
    @Override
    public String toString() {
        //以[a,b,c]格式输出
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i=0; i<size; i++) {
            sb.append(array[i]+",");
        }
        sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
        return sb.toString();
    }
    
    public static void main(String[] args) {
        WriteArrayList<Integer> wal = new WriteArrayList<>();
        wal.add(11);
        wal.add(12);
        wal.add(13);
        System.out.println(wal);
    }
    
}

练习二:在练习一的基础上增加数组扩容

/**
 *  增加数组扩容
 */
public class WriteArrayList<E> {
    
    private static Object[] array;
    private int size;//数组下标
    private static final int DEFAULT = 10;
    
    public WriteArrayList() {
        array = new Object[DEFAULT];
    }
    
    public WriteArrayList(int index) {
        array = new Object[index];
    }
    
    public void add(E data) {
        //什么时候扩容?
        if(size==array.length) {
            //如何扩容?
            Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
            System.arraycopy(array, 0, newArray, 0, array.length);
            array = newArray;
        }
        array[size++] = data;
    }
    
    @Override
    public String toString() {
        //以[a,b,c]格式输出
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i=0; i<size; i++) {
            sb.append(array[i]+",");
        }
        sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
        return sb.toString();
    }
    
    public static void main(String[] args) {
        WriteArrayList<Integer> wal = new WriteArrayList<>();
        for(int i=0; i<40; i++) {
            wal.add(i);
        }
        System.out.println(wal);
    }
    
}

练习三:在练习二的基础上增加set()、get()方法,增加数组边界检测

/**
 *  增加set()、get()方法
 *  增加数组边界检查(判断索引是否合法)
 */
public class WriteArrayList<E> {
    
    private static Object[] array;
    private int size;//数组下标
    private static final int DEFAULT = 10;
    
    public WriteArrayList() {
        array = new Object[DEFAULT];
    }
    
    public WriteArrayList(int index) {
        //加入判断
        if(index<0) {
            throw new RuntimeException("容器的容量不能为负数:"+index);
        } else if(index==0) {
            array = new Object[DEFAULT];
        } else {
            array = new Object[index];
        }
    }
    
    public void add(E data) {
        //什么时候扩容?
        if(size==array.length) {
            //如何扩容?
            Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
            System.arraycopy(array, 0, newArray, 0, array.length);
            array = newArray;
        }
        array[size++] = data;
    }
    
    @Override
    public String toString() {
        //以[a,b,c]格式输出
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i=0; i<size; i++) {
            sb.append(array[i]+",");
        }
        sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
        return sb.toString();
    }
    
    public E get(int index) {
        checkIndex(index);
        return (E)array[index];
    }
    
    public void set(int index, E data) {
        checkIndex(index);
//      //索引合法判断,索引区间应满足[0,size)
//      if(index<0||index>size-1) {
//          //不合法,手动抛出异常
//          throw new RuntimeException("索引不合法:"+index);
//      }
        array[index] = data;
    }

    /**
     *  由于许多地方都需要判断index索引是否合法,
     *  所以在此处写一个独立的方法,需要时直接调用即可
     */
    public void checkIndex(int index) {
        //索引合法判断,索引区间应满足[0,size)
        if(index<0||index>size-1) {
            //不合法,手动抛出异常
            throw new RuntimeException("索引不合法:"+index);
        }
    }

    public static void main(String[] args) {
        WriteArrayList<Integer> wal = new WriteArrayList<>();
        for(int i=0; i<40; i++) {
            wal.add(i);
        }
        System.out.println(wal.get(10));
        
        wal.set(1,100);
        System.out.println(wal);
        
    }
    
}

练习四:在练习三的基础上增加remove()、size()、isEmpty()方法的实现

/**
 *  增加2种remove()实现方法
 *  增加size()、isEmpty()方法
 */
public class WriteArrayList<E> {
    
    private static Object[] array;
    private int size;//数组下标
    private static final int DEFAULT = 10;
    
    public WriteArrayList() {
        array = new Object[DEFAULT];
    }
    
    public WriteArrayList(int index) {
        //加入判断
        if(index<0) {
            throw new RuntimeException("容器的容量不能为负数:"+index);
        } else if(index==0) {
            array = new Object[DEFAULT];
        } else {
            array = new Object[index];
        }
    }
    
    public void add(E data) {
        //什么时候扩容?
        if(size==array.length) {
            //如何扩容?
            Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
            System.arraycopy(array, 0, newArray, 0, array.length);
            array = newArray;
        }
        array[size++] = data;
    }
    
    @Override
    public String toString() {
        //以[a,b,c]格式输出
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i=0; i<size; i++) {
            sb.append(array[i]+",");
        }
        sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
        return sb.toString();
    }
    
    public E get(int index) {
        checkIndex(index);
        return (E)array[index];
    }
    
    public void set(int index, E data) {
        checkIndex(index);
//      //索引合法判断,索引区间应满足[0,size)
//      if(index<0||index>size-1) {
//          //不合法,手动抛出异常
//          throw new RuntimeException("索引不合法:"+index);
//      }
        array[index] = data;
    }

    /**
     *  由于许多地方都需要判断index索引是否合法,
     *  所以在此处写一个独立的方法,需要时直接调用即可
     */
    public void checkIndex(int index) {
        //索引合法判断,索引区间应满足[0,size)
        if(index<0||index>size-1) {
            //不合法,手动抛出异常
            throw new RuntimeException("索引不合法:"+index);
        }
    }

    public void remove(int index) {
        //数组中需要移动的元素个数
        int numMoved = array.length - index - 1;
        if(numMoved>0) {
            //底层原理:数组的拷贝
            System.arraycopy(array, index+1, array, index, numMoved);
        }
        array[--size] = null;
    }
    
    public void remove(E data) {
        for(int i=0; i<size; i++) {
            if(array[i].equals(data)) {
                remove(i);
            }
        }
    }
    
    public int size() {
        return size;
    }
    
    public boolean isEmpty() {
        return size==0?true:false;
    }
    
    public static void main(String[] args) {
        WriteArrayList<Integer> wal = new WriteArrayList<>();
        for(int i=0; i<40; i++) {
            wal.add(i);
        }
        System.out.println(wal.get(10));
        
        wal.set(1,100);
        System.out.println(wal);
        
        wal.remove(2);
        System.out.println(wal);
        
        WriteArrayList<String> s = new WriteArrayList<String>();
        s.add("A");
        s.add("B");
        s.add("C");
        s.add("D");
        System.out.println(s);
        s.remove(1);
        System.out.println(s);
        s.remove("D");
        System.out.println(s);
        
        System.out.println(s.size());
        System.out.println(s.isEmpty());
    }
    
}

学习StringBuilder类,及它提供的append()、setCharAt()方法
掌握数组拷贝arraycopy()方法:
System.arraycopy(被复制的数组, 从第几个元素开始复制, 要复制到哪个数组, 粘贴到什么位置, 一共要复制多少个元素);
自己独立重写ArrayList实现类的功能

练习1到4心得:

下面的代码是我独立完成的,与练习4的代码的本质区别是:size和array.length具体代表的含义。
我下面的代码中size代表容器中元素的个数,array.length表示容器大小,由于数组扩容,容器大小一般大于元素个数。
注意==与equals的区别。

public class WriteArrayList02<E> {

    private Object[] array;
    private int size;
    private static final int DEFAULT = 10;
    
    public WriteArrayList02() {
        array = new Object[DEFAULT];
    }
    
    public WriteArrayList02(int index) {
        if(index == 0) {
            array = new Object[DEFAULT];
        }else if(index<0) {
            throw new RuntimeException("索引不能为负数:"+index);
        }else {
            array = new Object[index];
        }
    }
    
    public void add(E element) {
        if(size==array.length) {
            Object[] newArray = new Object[array.length+(array.length>>1)];
            System.arraycopy(array, 0, newArray, 0, array.length);
            array = newArray;
        }
        array[size++] = element;
    }
    
    public void set(int index, E element) {
        checkIndex(index);
        array[index] = element;
    }
    
    public E get(int index) {
        checkIndex(index);
        return (E)array[index];
    }
    
    public void checkIndex(int index) {
        if(index<0||index>=size) {
            throw new RuntimeException("索引异常:"+index);
        }
    }
    
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i=0; i<size; i++) {
            sb.append(array[i]+",");
        }
        sb.setCharAt(sb.length()-1,']');
        return sb.toString();
    }
    
    public void remove(E element) {
        for(int i=0; i<size; i++) {
            if(array[i].equals(element)) {
                remove(i);
            }
        }
    }
    
    public void remove(int index) {
        System.out.println(array.length);
        //1,2,3,4,5,6,7
        int numCopy = size - index - 1;
        if(numCopy<0) {
            throw new RuntimeException("索引异常:"+index);
        }else if(numCopy==0) {
            array[size] = null;
        }else {
            System.arraycopy(array, index+1, array, index, numCopy);
        }   
        //array[size-1] = null;
        size--;
        System.out.println(array.length);
    }
    
    public int size() {
        return size;
    }
    
    public boolean isEmpty() {
        return size==0?true:false;
    }
    
    public static void main(String[] args) {
        WriteArrayList02<String> wal = new WriteArrayList02<>();
        for(int i=0; i<40; i++) {
            wal.add(i+"");
        }
        System.out.println(wal);
        
        wal.set(1,"11");
        System.out.println(wal);
        
        System.out.println(wal.get(39));
        
        wal.set(39,"12");
        System.out.println(wal);
        
        wal.remove(0);
        System.out.println(wal);
//      wal.remove(38);
//      System.out.println(wal);
        wal.remove("12");
        System.out.println(wal);
        System.out.println(wal.size());
        System.out.println(wal.isEmpty());
    }
    
}

LinkedList链表存储结构

最后

感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

上一篇下一篇

猜你喜欢

热点阅读