java集合1

目录

数组的缺点

集合

集合的框架

(单列集合) Collection接口和它的实现类

 ArrayList类的介绍:


数组的缺点

1、长度开始时必须指定,一旦指定,不能更改
2、保存的必须是同一数据类型的元素
3、对数组元素的增删改查(crud)操作比较麻烦

集合

1、可以动态保存任意多个对象(类型可以不同) ,如果是基本数据类型会自动装包
2、集合含有许多方法,方便进行crud操作

集合的框架

图一:java集合1

 图二:java集合1

分析:
1、集合主要主要是两组(单列集合[图一] 、双列集合[图二])
2、Collection 接口有两个重要的子接口 List Set , 他们的实现子类都是单列集合
3、Map 接口的实现子类 是双列集合,存放的K-V

(单列集合) Collection接口和它的实现类

Collection接口下又有两个接口继承了它,分别是List接口 和 Set接口
分析:
1、Collection接口的所有实现子类可以存放多个元素,每个元素都可以是Object
2、对于List接口的实现子类,可以存放重复的元素,而对于Set接口的实现子类,不允许存放重复元素
3、List接口的实现子类中的元素是有序的,而Set接口中的实现子类是无序的

 对Collection集合作进一步说明
Collection接口形式:public interface Collection<E> extends Iterable<E>

说明:
1、 <E>是泛型,集合可以使用泛型向集合中传入一个参数(引用类型),来指定元素存储的类型,如果不传默认是Object
2、在创建对象时 可以使用泛型来限定元素的存储类型
3、集合存储的元素是引用类型(对象),如果存储基本数据类型,系统自动会包装成引用类型对象
具体实现:Collection是一个接口,所以只能通过实现子类来创建对象,这里以ArrayList来创建对象

public class Test {
    public static void main(String[] args) {
        /*
        Collection<E> c = new ArrayList<T>();
        在多态实现时,编译看左边,左边的泛型就会控制集合中元素的类型必须是 E 或者是E的子类
                    右边的泛型,是运行时类型其中的T必须和E一致 或者 是E的子类
                    一般形式:左边的泛型存在右边没有,或者右边的泛型存在左边没有

        例如:Collection<String> c = new ArrayList<T>();
        要求 c这个集合中 只能添加String 类型的元素 通过add方法 添加元素
        Collection<String> c = new ArrayList<>();
        c.add("hello world");
        c.add("!");
        System.out.println(c);
        结果是:[hello world, !]

        如果添加的元素不是String类型,则会直接编译不通过
         */
        Collection<String> c = new ArrayList<>();
        c.add("hello world");
        c.add("!");
        System.out.println(c);
    }
}

 ArrayList类的介绍:

ArrayList是一个集合类,可以存储多个重复的元素,且底层是一个数组

ArrayList类的构造方法:
1、无参构造器

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
// DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是一个空数组

 在使用无参构造器创建对象时,在底层的数组会是一个空数组
java集合1

当添加第一个元素时,它会自动扩容成含有10个容量的数组
java集合1        java集合1

 可以发现,数组的容量发生了变化
查阅源码得到

private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
//DEFAULT_CAPACITY数值为10 无参构造器minCapacity=0 

 会得到一个容量为10的数组

2、有参构造器

 public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

 会得到一个给定容量大小的数组

ArrayList集合类的扩容

实质:对底层数组的更新,通过Arrays.copyOf返回一个新的长度的数组
扩容的细节:1、使用无参构造器构造对象,初始化容量为0,第一次添加元素,则扩容为10,如果还需要再次扩容,则扩大为1.5倍
                      2、使用有参构造器构造对象,初始化容量为指定的大小,如果需要扩容,则直接扩大1.5倍

Collection中定义的一些抽象方法,在这里具体通过ArrayList创建的对象,所以这里的方法我们认为是ArrayList重写Collection的方法

ArrayList类中的add 方法
源码:

 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

对源码的解释说明:
1、ArrayList集合类的底层是一个数组:transient Object[] elementData;
elementData数组存储着元素,ArrayList类对它进行维护
2、在进行添加元素之前需要先进行一个判断,判断这个底层数组是否已经被装满,如果被装满就需要对数组进行扩容,如果没有就直接在末尾添加元素即可
判断是否需要扩容的源码

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

3、因为集合可以动态扩容,所以需要有个变量来记录存储了多少元素,size来记录已经存储的元素的个数

ArrayList类中的size 方法

作用:得到ArrayList对象中的元素个数
格式:对象名.size();
实例演示:

public class Test {
    public static void main(String[] args) {
      ArrayList list = new ArrayList();
      list.add("中");
      list.add("国");
        System.out.println(list.size());
        /*
        结果:2
         */
    }
}

ArrayList类中的get 方法

作用:通过索引取得索引位置上的元素
格式:对象名.get(int index);
实例演示:

public class Test {
    public static void main(String[] args) {
      ArrayList list = new ArrayList();
      list.add("中");
      list.add("国");
        System.out.println(list.get(0));
        /*
        结果:中
         */
    }
}

ArrayList类中的indexOf方法
作用:返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1
格式:对象名.indexOf(Object o);
实例演示:

public class Test {
    public static void main(String[] args) {
      ArrayList list = new ArrayList();
      list.add("中");
      list.add("国");
        System.out.println(list.indexOf("中"));
    }
}

类似的方法还有:
对象名.remove(int index);        删除并返回指定索引的元素
对象名.remove(Object o);        删除指定的对象并返回布尔值,如果删除成功则返回true,否则返回false
对象名.set(int index,Object o);        用指定的对象替换指定索引位置的元素

ArrayList类中的sort 方法
作用:对数组元素按照比较器排序
格式:对象名.sort(Comparator<? super E> c)
sort括号中接口的定义
方法一:匿名内部类

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> alist = new ArrayList<>();
        alist.add(1);
        alist.add(0);
        alist.add(-3);
        alist.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        System.out.println(alist);
    }
}

方法二:创建类来实现

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> alist = new ArrayList<>();
        alist.add(1);
        alist.add(0);
        alist.add(-3);
        ComparatorDemo c = new ComparatorDemo();
        alist.sort(c);
        System.out.println(alist);
    }
}
class ComparatorDemo implements Comparator<Integer>{

    @Override
    public int compare(Integer o1, Integer o2) {
        return o1-o2;
    }
}

方法三:直接将方法作为参数

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> alist = new ArrayList<>();
        alist.add(1);
        alist.add(0);
        alist.add(-3);
        alist.sort((Integer o1,Integer o2)->{ return o1-o2; });
        System.out.println(alist);
    }
}

未完待续......

上一篇:查找排序算法


下一篇:Pandas还是要保持手感的 - 案例整理(持续收集)